vue讲解基础知识点总结

https://juejin.im/post/5d5375a0f265da03db076f59#heading-32

vue基础知识点

1. vue中常见的指令

1.1 数据相关的指令

  • v-text:
    • 主要用来更新textContent
    • 双大括号的方式会将数据解释为纯文本,而非HTML



{{msg}}

  • v-html:

    • 命令模式可以解释html
  • v-model:
    • 用于在表单上创建双向数据绑定

hello {{somebody}}

上面这个例子中直接在浏览器input中输入别的名字,下面的p的内容会直接跟着变。这就是双向数据绑定。

v-model:仅仅是一个语法糖,相当于 :value+@input


input事件:当输入框中的数据改变时发生

1.2属性相关的指令:

  • v-bind ``>
    • 用于绑定html标签中的属性
      • v-bind:href="数据"
      • 简写: :href = "数据"
百度
百度


1.3 条件指令:

  • v-if v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。
yes

如果属性值ok为true,则显示。否则,不会渲染这个元素。

  • v-else v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。
yes
No
  • v-else-if v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。
A
B
C
Not A,B,C
  • v-show

hello world

也是用于根据条件展示元素。和v-if不同的是,如果v-if的值是false,则这个元素被销毁,不在dom中。但是v-show的元素会始终被渲染并保存在dom中,它只是简单的切换css的dispaly属性。

注意:v-if有更高的切换开销 v-show有更高的初始渲染开销。 因此,如果要非常频繁的切换,则使用v-show较好;如果在运行时条件不太可能改变,则v-if较好

特别提醒

v-show需要放到一个真实的dom上,不能放在template上面

1.4 循环指令:

v-for 遍历数组

 

{{value}}

注意:在使用v-for过程中,要绑定唯一的key,key尽量不要绑定index,如果有id尽量绑定id

{{value}}

特别提醒

建议不要在与v-for相同的元素上使用v-if。因为v-for指令的优先级高于v-if当它们处于同一节点。v-for 的优先级比v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。

1.5 两个特殊的属性:class style

  • class
    • :class="数据"
    • :class="三元运算符"
    • :class="{类名:boolean}"
    • :class="{类名1:boolean,类名2:boolean}"
    • 类名中有-,需要使用引号包起来
    • :class="['类名']"


这是一个p标签

这是一个p标签

这是一个p标签

这是一个p标签

这是一个p标签

这是一个p标签

这是一个p标签

这是一个p标签

  • style的用法

这是一个p标签


2. vue 中挂载的属性及方法

2.1 el

el指定app管理的边界

面试题

如何通过$el获取到更新后的dom元素? 答:在下一下事件环中得到更新后dom元素

2.2 data

数据模型

2.3 methods

2.4 computed

计算属性,依赖于data中的数据

计算属性和方法的区别:

  • 1,它们两个本质都是函数
  • 2,用的时候,方法需要调用,计算属性是当成数据来使用
  • 3,方法没有缓存,计算属性有缓存

2.5 filters

过滤器

过滤器的简单使用:

2.6 components

组件:三部曲

  1. 定义组件
  2. 注册组件
  3. 使用组件

组件的简单使用:

2.7 钩子函数

生命周期方法

2.8 $watch

$watch可以监控Data中的数据,通过$watch得到值,肯定是更新后的值 使用

vm.$watch( "name", function(newValue,oldValue){ } )

2.9 $nextTick()

vue中的$nextTick主要涉及到vue中DOM的异步更新 nextTick应用场景及原因

  • 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中

原因:在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

  • 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

Vue的官方文档中详细解释

Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.thenMessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0)代替。

例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用。

2.10 $set

$set可以给data中动态地添加一个数据,前提是只能给对象中添加数据

示例

3. 事件模型

事件三要素: 事件源,事件类型,监听器

语法:v-on: 处理事件 或 @处理事件

3.1 事件类型

  • 鼠标事件:
    • click:单击事件
    • dblclick:双击事件
    • mouseover:鼠标进入事件
    • mouseout:鼠标移开事件
    • mouseenter:鼠标进入事件
    • mouseleave:鼠标离开
    • mousedown:鼠标按下
    • mousemove:鼠标移动
    • mouseup:鼠标抬起
  • 键盘事件:
    • keyup:键盘抬起
    • keypress:按键并产生第一个字符时
    • keydown:键盘按下
  • UI事件:
    • scroll:滚动条事件
    • resize:浏览器窗口改变
    • load:文档加载完毕
    • unload:文档未加载
  • 焦点事件:
    • focus:焦点事件
    • blur:失去焦点
  • 表单事件:
    • change:数据发生改变时
    • submit:提交

注意:mouseover / mouseout 与 mouseenter / mouseleave的区别

  • 当绑定事件的元素里面没有子元素的时候,两组触发效果是一致的。
  • 当绑定事件的元素里面有子元素的时候,鼠标经过绑定mouseover的当前元素以及它里面的子元素的时候,都会触发, 而经过绑定mouseenter的元素时,只会在鼠标刚进入的时候触发,当进入其子元素的时候,是不会再触发的了。

总结

  • 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。对应mouseout

  • 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。对应mouseleave

3.2 事件对象

当事件发生时,事件对象中保存了很多信息,如点击的坐标。 $event 固定的名字

示例:

3.3 事件修饰符

  • stop:阻止冒泡
  • prevent:阻止默认事件
  • capture:冒泡改为捕获
  • self:只处理发生在自己身上的事件,不理会冒泡或捕获(把self放到谁的身上,谁就不会触发)
  • once:只执行一次

示例:

3.4 键盘事件修饰符

  • keyCode 键盘修饰符

示例:

  • 自定义按键名称
// 自定义按键名称
Vue.config.keyCodes.ent = 13;

// 页面引用


4. 组件

4.1 全局组件

全局组件 : 定义全局组件,在每个组件中都可以进行引用

语法:

Vue.component("组件名",{template:"组件内容"})

示例:

4.2 局部组件:

组件:三部曲

  1. 定义组件
  2. 注册组件
  3. 使用组件

示例:

5. 组件之间的数据传递

5.1 父传子

父传子 : 父中有数据,传递给子,

步骤:

1,确定父中有数据 2,在父组件的模板中通过属性绑定把数据绑到子组件上 3,在子组件中定义props属性,用来接收父传递过来的数据 4,在子组件的模板就可以使用接收过来的数据了

示例:

属性校验:

总结:

父绑定数据 子接收数据

5.2 子传父

过程:

  1. 在父组件模板中,给子组件添加一个事件监听
  2. 在子组件中,某个时间通过this.$emit发出这个事件,发出事件的同时就可以携带数据
  3. 当父中的方法触发,数据作用这个方法的第一个参数

示例:

6. vue脚手架

6.1 脚手架的安装

  1. 安装node

2. 安装nrm

npm i nrm -g

  1. 切换安装源

    • 查看安装源
      nrm ls



      切换安装源 nrm use taobao

  2. 安装vue的脚手架

npm i -g @vue/cli

  1. 创建vue项目

vue create myvue

  1. 进入项目

cd myvue

  1. 启动项目

npm run serve

  1. 项目目录

6.2 组件的使用

  1. 组件的定义

2. 组件的使用(main.js主接口)


7. router(路由)的使用

7.1 基本路由

html代码


Hello App!

Go to Foo Go to Bar

script代码


// 1\. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: '
foo
' } const Bar = { template: '
bar
' } // 2\. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是 // 通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3\. 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes // (缩写) 相当于 routes: routes }) // 4\. 创建和挂载根实例。 // 记得要通过 router 配置参数注入路由, // 从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app') // 现在,应用已经启动了!

通过路由

我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 his.$route 访问当前路由:

7.2 嵌套路由

  1. 嵌套路由的组件
  1. router的注册

7.3 动态路由

  • list列表 需要动态跳转的列表
  • router.js中对路由进行相关的配置
  • 调转页面对数据进行获取

7.4 编程路由

格式

router.push(location, onComplete?, onAbort?)

注意:

在 Vue 实例内部,你可以通过 $router访问路由实例。因此你可以调用 this.$router.push

示例:

7.5 重定向

示例:

8. axios的使用

  1. 安装axios

npm install axios

  1. 引入axios

import axios from 'axios';

  1. axios的简单使用

9. vue中的生命周期方法

当vue的实例创建时,会伴随一系列的方法运行,称作生命周期函数

9.1 beforeCreate()

  1. 这是第一个生命周期函数,表示实例完全被创建之前会被执行
  2. 该方法执行时,data和methods中的数据还没有初始化

9.2 created()

  1. 该方法执行时,data与mathods中的数据已经初始化好了
  2. 要操作data,methods中的数据,最早只能在该处进行操作

9.3 beforeMount()

  1. 表示模板已经在内存中编辑完成,但尚未将模板渲染到页面中
  2. 该方法执行时,页面中的元素没有真正替换过来,只是一些模板字符串

9.4 mounted()

  1. 表示内存中的模板,已经挂载到页面中,用户可以看到渲染后的页面
  2. 如果通过某些插件操作页面上的DOM节点,最早在该方法中执行

9.5 beforeUpdate()

  1. 表示:当前页面没有更新,但是数据已经更新

9.6 updated()

  1. 表示:页面和数据均已经更新

9.7 beforeDestory()

  1. 实例从运行阶段进入销毁阶段,此时实例中的东西仍处于可用状态

9.destoryed()

  1. 所有组件完全被销毁

10. vue中组件之间的传值方式

10.1 props 与 $emit

父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的。

props 与 $emit的简单使用


注意 使用$emit 触发父类绑定的方法时,触发的名称必须全部是小写,若父类绑定使用到小驼峰,则在触发时,全部变成小写,驼峰之间用-隔开

10.2 attrs和listeners

可以实现父组件与孙子组件之间的数据的传递 this.attrs如果子接受的数据没有用到,把数据保存在attrs中

$attrs的简单使用

特别提醒

父组件中所绑定的传给父组件的属性,都存放在$attrs中,若在子组件中不接收,直接进行绑定,可以使用:

v-bind="this.$attars"

$listenners的简单使用

触发父传递的click事件: @click="listeners.click()"触发父传递多个事件:v-on="listeners"

10.3 parent与children

  1. $parent 获取父组件的实例,可以以此来调用父组件中的方法。

    • 示例:
    • this.$parent.cut();

  2. $children 获取所有的儿子, 可以以此来获取子组件中的数据

    • 示例:
    • this.$children[0].msg = "张三"

特别提醒

parent: 获取的是父亲的实例children:获取的是所有的子组件的实例
children:获取的是所有子组件的实例

10.4 provice 与 inject的使用

10.5 refs的使用

ref 与refs是成对使用 ref 用于定义 $refs用户获取

10.6 自定义$dispatch

$dispatch 是挂载到Vue实例上的一个方法, 自动向上父类中查找触发的方法,如果该方法存在就触发

示例

10.7 事件总线eventBus

原理

事件总线是,在vue的原型上,挂载一个$eventBus事件(名字自己起),通过$on进行绑定事件, 先在事件中心中注册一些事件 在需要的位置就可以通过$emit去发布事件(触发事件)

示例

10.8 数据传递的语法糖

在数据进行传递的时候,数据的传递与触发的方法结合,可以有比较简便的语法糖,更加方便程序的开发,但是与此同时也有一定的难度,不是很容易懂。下面就简单的介绍几种语法糖。

10.8.1 .sync语法糖

.sync@update:data的语法糖,data是vue中data中的数据

在给子类传递数据的时候,通过.sync对属性进行限定,在子类中可以直接触发update:数据名称来修改父类中对应的数据,该方法可以省去父类中修改属性的方法。

没有使用.sync之前

  • 传递数据,绑定属性
  • 修改数据值,绑定修改的方法
  • 触发绑定的修改方法,调用修改方法

示例

使用.sync之后

  • 传递数据,绑定属性.sync
  • 触发update:数据名,直接修改数据

没有简化: 简化后:

示例

特别注意

update是规定的触发的方法,update冒号后面跟的必须是父类中要修改的数据的数据名

10.8.2 v-model语法糖

v-model:value@input的语法糖,绑定的属性必须是value

在给子类传递数据的时候,直接使用v-model进行绑定,在子类中,可以触发input事件,来达到修改数据的目的

示例

特别注意

v-model 相当于 :value + @input 相当于上述方法的简写

11 vue中数据监控的原理(数据劫持)

数据监控: : 监控数据的获取与改变,可以简称为数据劫持。

vue中data数据的监控原理:

代码如下:

// 数据的监控,监控数据的获取与改变
// vue中data数据的监控原理
obj = {
    name: "wangcai",
    age:18
};

function obServe(obj){
    if(typeof obj ``= "object"){
        for(key in obj){
            defineReactive(obj,key,obj[key]);
        }
    }
}

function defineReactive(obj,key,value){
    obServe(value);
    Object.defineProperty(obj,key,{
        get(){
            console.log("get...");
            return value;
        },
        set(val){
            console.log('set... :');
            obServe(val);
            value = val;
        }
    })
}

// defineProperty是数组是无效的
//解决方式如下:
// vue中封装了数据的所有的方法,此处只做列举
let arr = ["push","slice","shift","unshift"]
arr.forEach(method=>{
    let old = Array.prototype[method];
    Array.prototype[method] = function(value){
        console.log("set...")
        old.call(this,value)
    }
})
//-----------------------------------------------------------
// 测试数组
// observer(obj)
// obj.age = [1,2,3] // set..
// obj.age.push(4)  // 设置值  defineProperty对数据是无效的
//-----------------------------------------------------------------
// 测试简单的对象
// obServe(obj)
// console.log(obj.name)    //get...
// obj.name = "hello"       // set...

// 测试嵌套的对象
// observer(obj)
// obj.name  // get...
// obj.name = "hello" // set...
// obj.age = { k:"kkkk" }  // set...
// obj.age.k = "mmmm"  // set...

12. 路由跳转的传值方式

在vue的路由跳转中有两种方式,分别是问号模式,和冒号模式,两者不能进行混合使用,

12.1 问号传值方式

格式

传值用户1 获取值{{this.$route.query.id}}

注意:使用问号进行传值的时候不需在router中特别设置路由

12.2 冒号传值方式

格式

传值用户2 配置router路由文件 path:"detail/:id", 获取值{{this.$route.params.id}}

13. 路由的生命周期方法

13.1 全局路由守卫

在全局中有三个路由守卫,分别是beforeEach,beforeResolve,afterEach

  1. beforeEach

    • 路由正在开始发生改变的时候开始调用。
    • 格式:
    • router.beforeEach((to, from, next) => {}
  2. beforeResolve

    • 所有组件中的路由守卫解析完毕之后,被调用
    • 格式:
    • router.beforeResolve((to, from, next) => {}
  3. afterEach

    • 当前的路由进入完毕之后,被调用
    • 全局后置钩子,不接受next函数
    • 格式:
    • router.afterEach((to, from) => {}

13.2 路由独享的守卫

  • beforeEnter
    • 当进入到路由的配置中,被调用

格式:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

13.3 组件内的守卫

在组件的内部存在整合三个路由组件,分别是beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

  • beforeRouteEnter

    • 在进入组件之前,被调用,
    • 此时的组件实例没有被创建,不能获取组件实例this
    • 示例:
  • beforeRouteUpdate

    • 当前路由发生改变的时候,
    • 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    • 可以访问组件实例 this
    • 格式:
    • beforeRouteUpdate ((to, from, next) => {}
  • beforeRouteLeave

    • 当离开该组件的时候被调用,
    • 可以访问组件实例 this
    • 格式:
    • beforeRouteLeave((to, from, next) => {}

13.4 总结

  1. 导航被触发。 beforeEach
  2. 在失活的组件里调用离开守卫 beforeRouterLeave
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

14 vue.config的简单配置

14.1 vue的简单配置+前端代理解决跨域

源码

// 基于node的 node不支持import语法
// 默认环境变量 NODE_ENV 生产环境   production development
let path = require('path');
module.exports = {

    // 配置开发环境(npm run serve)或生产环境(npm run build)url
    publicPath:process.env.NODE_ENV ``= 'production'? 'http://www.abcd.cn':'/',

    //打包后的资源放入的文件夹,默认未放入文件夹
    assetsDir:'asserts',

    //打包后生成的文件夹,默认是dist
    outputDir:'./dist',

    // 是否使用自己的内部模板 一般不使用
    runtimeCompiler:false,

    // 打包后删除生成的.map文件 不再使用sourcemap
    productionSourceMap:false,

    chainWebpack:config=>{
        // 可以获取到webpack的配置 在增加一些自己的逻辑
        // 配置目录别名 别名叫+
        config.resolve.alias.set('_c',path.resolve(__dirname,'src/components'));
        config.resolve.alias.set('_v',path.resolve(__dirname,'src/views'));
    },

    //webpack配置,到时候会合并到默认的webpack中。
    configureWebpack:{ // webpack-merge
        plugins:[],
        module:{}
    },

    // 开发 服务时使用  上线时不需要 解决跨域的问题
    devServer:{
        proxy:{
            '/api/getUser':{
                target:'http://localhost:3000',
                pathRewrite:{
                    '/api':''
                }
            }
        }
    },

    //第三方插件的配置
    pluginOptions: {
        'style-resources-loader': {
            preProcessor: 'less',
            patterns: [
                path.resolve(__dirname,'src/assets/common.less')
            ]
        }
    }
}

14.2 后端代理解决跨域问题

源码

let express = require('express');
let app = express();

// 在后端配置,让所有的人都可以访问我的api接口
app.use('*', function (req, res, next) {
    // 允许哪些客户端来访问我
    res.setHeader("Access-Control-Allow-Origin","*");
    // 允许可以添加哪些头,然后来访问我
    res.setHeader("Access-Control-Allow-Headers","*");
    // res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');

    // 允许哪些方法来访问我
    res.setHeader("Access-Control-Allow-Methods","OPTIONS,PUT,DELETE");
    // res.header('Access-Control-Allow-Methods', '*');

    // 可以每隔半小时,来发送一个options请求--试探请求
    res.setHeader("Access-Control-Max-Age","1800");

    // 请求的类型编码
    res.header('Content-Type', 'application/json;charset=utf-8');

    // 允许客户端携带凭证,处理cookie信息,如果有,并且不对每次请求都新开一个session
    res.setHeader("Access-Control-Allow-Credentials",true);
    next();
});

15. 路由元信息

路由的元信息一般可用于权限的校验

定义路由的时候可以配置 meta 字段

配置meta字段,该字段配置为对象信息

一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

示例:

你可能感兴趣的:(vue讲解基础知识点总结)