Vue 知识总结

前言:

基于vue 2+ 写一份知识总结,可以说是学习笔记

目录:

一、vue实例的基本结构
二、vue事件处理、绑定属性
三、vue指令、自定义指令
四、vue过滤器
五、vue数据监听
六、vue组件
七、vue-router
八、axios

一、Vue 实例的基本结构

Vue官网API

 

{{msg}}

 Welcome
var vm = new Vue({
  el: '#app', //等价于后面的 .$mount('#app') 用其中之一就可以了
  render: h => h(App), //理解不够深入,参考(https://cn.vuejs.org/v2/api/?#render)
  data: { 
    //页面响应的数据都放在这里如上(组件只接受 function 且必须返回一个对象),zhicvm.$data 访问这里面的data
    msg: 'Welcome',
  },
  props:{
    //props 可以是数组或对象,接收任何值
  },
  methods:  {
    //页面或组件定义的方法的集合,可通过 vm.reset() 直接调用
    reset: function(){
      this.msg = '这是重新设置之后的数据'
    }
  },
  computed: {
    //计算属性(computed)与方法(methods) 类似,如果计算数据量比较大,建议放到这里
    //计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。
    //参考(https://cn.vuejs.org/v2/api/?#computed)
  },
  components:{
    // 局部组件注册的地方
    'component-a': ComponentA,
    'component-b': ComponentB
  },
  directives: {
    // 局部指令注册的地方
    focus: {
      // 指令的定义
      inserted: function (el,binding) {
        el.focus(); 
      }
    }
  },
  filters:{
    // 局部过滤器注册的地方
  },
  //生命周期钩子
  beforeCreate: function (){}, //在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
  created: function (){},//在实例创建完成后被立即调用。
  beforeMount: function (){},//在挂载开始之前被调用:相关的 render 函数首次被调用。
  mounted: function (){},//el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
  beforeUpdate: function (){},//数据更新时调用,发生在虚拟 DOM 打补丁之前。
  updated: function (){},//由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
  beforeDestroy: function (){},//实例销毁之前调用。在这一步,实例仍然完全可用。
  destroyed: function (){
    //Vue 实例销毁后调用。
    //调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
  },
}).$mount('#app')
二、Vue 事件处理、绑定属性

v-on:

1、绑定事件监听器。用在普通元素上时,只能监听原生 DOM 事件(如:click、keyup/down、mouseenter/over/move/down/out 等)。也可以监听自定义事件即 methods 里面的事件。
2、在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性:v-on:click="handle('ok', $event)"。

修饰符:
.stop - 调用 event.stopPropagation()。阻止冒泡
.prevent - 调用 event.preventDefault()。阻止默认事件
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
用法:











.
.
.
  • v-on 还提供了按键修饰符
键盘按钮的别名
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
// 可以通过全局 `config.keyCodes` 对象自定义按键修饰符别名
// 使用 方式 `v-on:keyup.f1` ,f1 这个名字你可以任意取,你知道是什么意思就可以了
Vue.config.keyCodes.f1 = 112

v-bind:

动态地绑定一个或多个特性,或一个组件 prop 到表达式。











. . .

三、Vue 指令、自定义指令

Vue指令:

v-text:



{{msg}}

v-html:

//输出真正的 HTML
data{ html:'我是真正的html' }

v-show:

//根据表达式之真假值,切换元素的 display CSS 属性。

Hello!

v-if、v-if-else、v-else:

//v-if 是“真正”的条件渲染,如果条件为假,dom不会渲染在页面当中
//v-show 会一直渲染在dom当中
//当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。

Yes

Yes

No

A
B
C
Not A/B/C

v-for:

//基于源数据多次渲染元素或模板块。
{{ item.text }}
//另外也可以为数组索引指定别名 (或者用于对象的键):val->对象的键值 key->对象的键 index->对象的下标

v-model:作用于 // 选择框 // 用 v-for 渲染的动态选项: . . .

v-pre:

//跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
//Mustache 标签:{{ }}
{{ this will not be compiled }}

v-cloak:

//这个指令保持在元素上直到关联实例结束编译
css:
[v-cloak] {
  display: none;
}
html:
{{ message }}

v-once:

只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。


This will never change: {{msg}}

comment

{{msg}}

  • {{i}}

Vue自定义指令:

指令的钩子函数: 一个指令定义对象可以提供如下几个钩子函数 (均为可选):

`bind`:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

`inserted`:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

`update`:1、所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
          2、指令的值可能发生了改变,也可能没有。
          3、你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。

`componentUpdated`:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

`unbind`:只调用一次,指令与元素解绑时调用。

钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。

`el`:指令所绑定的元素,可以用来直接操作 DOM 。

`binding`:一个对象,包含以下属性:
    `name`:指令名,不包括 `v-` 前缀。
    `value`:指令的绑定值,例如:`v-my-directive="1 + 1"` 中,绑定值为 `2`。
    `oldValue`:指令绑定的前一个值,仅在 `update` 和 `componentUpdated` 钩子中可用。无论值是否改变都可用。
    `expression`:字符串形式的指令表达式。例如 `v-my-directive="1 + 1"` 中,表达式为 `"1 + 1"`。
    `arg`:传给指令的参数,可选。例如 `v-my-directive:foo` 中,参数为 `"foo"`。
    `modifiers`:一个包含修饰符的对象。例如:`v-my-directive.foo.bar` 中,修饰符对象为 `{ foo: true, bar: true }`。

`vnode`:Vue 编译生成的虚拟节点。移步(https://cn.vuejs.org/v2/api/#VNode%E6%8E%A5%E5%8F%A3) 来了解更多详情。

`oldVnode`:上一个虚拟节点,仅在 `update` 和 `componentUpdated` 钩子中可用。
// 注册一个全局自定义指令 `v-focus`
// 在这里需要注意一下,给一个全局指令命名的时候不要加 `v-` 前缀,用在dom的时候再加上
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el,binding) {
    // 聚焦元素
    el.focus();
    console.log(binding.value) //=>666
  }
})

//如果想注册局部指令,组件中也接受一个 directives 的选项:
directives: {
  focus: {
    // 指令的定义
    inserted: function (el,binding) {
      el.focus(); 
      console.log(binding.value) //=>666
    }
  }
}

//然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:
  // 6666 可用data 里面的变量替换,建议传简单数据类型

一个正常的业务不可能只有一个指令,如果把所有的指令都注册在main.js里面会不好管理,所以最好放在一个统一文件 directives.js
这里就产生了两个问题:
1、怎么把directives.js 这个文件引用到main.js
2、Vue.directives() 支不支持链式调用(因为老版本angular 支持,所以做一个假想)

// 第二个问题很好解决,经过测试,Vue.directives() 不支持链式调用 `Vue.directives().directives()`

// 第一个问题:经过查阅相关资料之后可以以插件的形式引入
// 这种方式引入暂时还没有发现有其他的问题

// main.js
import directives from './directives.js'
Vue.use(directives);

// directives.js
export default{
  // install 方法会默认在main.js里面调用
  install(Vue){
    Vue.directive('focus',{
      inserted(el,binding){
        el.focus();
      }
    });
    Vue.directive('data',{
      inserted(el){
        console.log(el)
      }
    });
    //有多个就继续往这里添加就好了
  }
}

四、Vue 过滤器

Vue 过滤器的用法

过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。
与指令的用法类似,但过滤器一定要有返回值,也不支持链式调用

这里需要注意的地方是,vue 2.0 之后移除了自带的过滤器

// 在双花括号中
{{ message | capitalize }}

// 在 `v-bind` 中
// 局部注册过滤器 filters: { // 首字母大写 capitalize: function (value) { // value 就是 ‘|’ 符号前面的值 if (!value) return ''; value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } // 注册全局过滤器 Vue.filter('capitalize', function (value) { if (!value) return ''; value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) })
// 过滤器传值
{{ number | dual(2) }}

Vue.filter('dual', function (value,type) {
  // 回调函数里面默认有 value ,在页面上传过来的值会依次添加在后面
  console.log(type)  // => 2
  if (!value) return '';
  if (typeof value !== "number") return alert(value + ' 不是数字');
  if( parseInt(type) === 2 ){
    return value = value > 10 ? value : '0' + value
  }
  return value
})
// 过滤器的插件用法,与 directives.js 一致
// main.js
import directives from './filters.js'
Vue.use(filters);

// filters.js
export default {
  install(Vue){
    Vue.filter('dual', function (value,type) {
      if (!value) return '';
      if (typeof value !== "number") return alert(value + ' 不是数字');
      if( parseInt(type) === 2 ){
        return value = value > 10 ? value : '0' + value
      }
      return value
    })
  }
}

五、Vue 数据监听

Vue 数据监听 watch

// watch 基本用法与注意事项
data: {
  a: 1,
  e: {
    f: {
      g: 5
    }
  },
  items: [
    { message: 'Foo' },
    { message: 'Bar' }
  ],
}
mounted: function(){
  this.a = 2;
  this.e.f.g = 10;
  this.$set(this.items, 0, { message: 'AAA' });  // $set 赋值
  this.items[0] = { message: 'AAA' };  // 直接赋值
},
watch: {
  // 最简单最直接的监听方式,能监听简单的数据变化,这种方法默认就是执行 handler: function(){}
  // 注意:这种方式监听不到对象的变化
  a: function(val, oldVal){
    console.log(val);  // => 变化之后的数据
    console.log(oldVal); // => 变化之前的数据
  },
  // 深度监听,这里要注意一下,这样的方式打印出来两个值都是变化之后的值
  // deep 的值默认为false,如果不写或者deep: false 都不能监听到对象值的变化
  e: {
    handler: function (val, oldVal) {
      console.log(val);  // => 变化之后的数据
      console.log(oldVal);  // => 变化之后的数据
    },
    deep: true, 
  },
  // 如果要精准监听的对象值的变化,可以用这种方法
  'e.f.g': function (val, oldVal) {
    console.log(val);  // => 变化之后的数据
    console.log(oldVal);  // => 变化之前的数据
  },
  // 监听数组
  // 由于 JavaScript 的限制,Vue 不能检测 this.items[0] = { message: 'AAA' }; 这种方式赋值的变化
  // 所以你要用 $set、或者数组变异的方法赋值
  items: function(val, oldVal){
    console.log(val);  // => 变化之后的数据
    console.log(oldVal);  // => 变化之后的数据
  },
}

Vue 数组更新检测

官网的介绍:由于 JavaScript 的限制,Vue 不能检测以下变动的数组
换句话来说:这样赋值不触发视图更新

  • 1、当你利用索引直接设置一个项时,例如:
this.items[indexOfItem] = newValue  // indexOfItem 是指数组的index 下标
  • 2、当你修改数组的长度时,例如:
this.items.length = newLength

要解决上面问题,你可以用以下方式解决:

1、Vue.set( target, key, value) ,set方法有下面3个参数
  • {Object | Array} target -- 给谁设置值(对象,数组)都可以
  • {string | number} key -- 给对象设值,key 就是对象的key,给数组设值,key 就是数组的下标 index
  • {any} value -- 添加任何值都可以
2、数组变异的方式

push():将一个或多个元素添加到数组的末尾,并返回新数组的长度。
pop():从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
shift():从数组中删除第一个元素,并返回该元素的值。
unshift():将一个或多个元素添加到数组的开头,并返回新数组的长度。
splice():通过删除现有元素和/或添加新元素来更改一个数组的内容。
sort():用就地( in-place )的算法对数组的元素进行排序,并返回数组。 sort 排序不一定是稳定的。默认排序顺序是根据字符串Unicode码点。
reverse():将数组中元素的位置颠倒。

六、Vue 组件

Vue 组件基础

组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。
注意:组件没有 el 这样根实例特有的选项;而根实例没有 props 这个子组件特有的属性

  • Vue.component( 组件名 ,{ 选项 }) 全局注册
// 全局注册组件的时候必须写在Vue实例创建之前
// 下面这几种方式是等价的
import Vue from 'vue'
var MyComponent = Vue.extend({
  template:"

我是全局组件

" }); Vue.component("my-component",MyComponent); // 注册组件,传入一个扩展过的构造器 Vue.component('my-component', Vue.extend({ /* ... */ })) // 注册组件,传入一个选项对象 (自动调用 Vue.extend) Vue.component('my-component', { /* ... */ })
  • 通常情况下一个组件肯定是由很多html标签组成的,如果全部写在template 里会非常难看且没有语法高亮提示,有没有其他解决办法?还真有
// 一个定义模板的方式是在一个 

// 另一个定义模板的方式是在一个