vue API 知识点(2)---选项总结

一、选项 / 数据

1.data

  当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例,如果 data 仍然是一个纯碎的对象,则所有的实例将被共享引用同一个数据对象。通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。

 

2.props

  props 可以是数组或者对象,用于接收来自父组件的数据。props 中使用对象可以配置高级选项,类型检测,自定义验证,设置默认值

  可以使用以下选项

    type:可以是原生构造函数中的一种:String、Number、Boolean、Array、Object、Date、Function、Symbol、任何自定义构造函数,或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。

    default:为 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回

    required:Boolean  定义该 prop 是否是必填项

    validator:function  自定义验证函数会将该 prop 的值作为唯一的参数带入。返回 false 就给默认值,控制台有警告

  props: {
    // 检测类型
    height: Number,
    // 检测类型 + 其他验证
    age: {
      type: Number,
      default: 0,
      required: true,
      validator: function (value) {
        return value >= 0
      }
    }
  }

 

3.propsData

  只用于 new 创建的实例中,创建实例时传递 props,主要作用时方便测试(开发的过程中基本用不到)

 

4.computed  计算属性

  计算属性将被混入到 Vue 实例中,所有 geter 和 setter 的 this 上下文自动地绑定为 Vue 实例

  注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。

  计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。注意,如果某个依赖(必须非响应式 property)在该实例范畴之外,则计算属性是不会被更新的。 

  <p>a + b 的结果是:{{ count }}</p>
  computed: {

    count(){

      return this.a + this.b
    }
  }

  计算属性 vs 方法

  <p>a + b 的结果是:{{ count() }}</p>
  methods: {
    count(){
      return this.a + this.b
    }
  }

  我们可以将同一函数定义为一个方法而不是一个计算属性,两种方式的最终结果确实是完全相同的。不同的是计算属性是基于他们的响应式依赖进行缓存的。只在相应响应式依赖发生改变时他们才会重新计算求值。就是说只要 a 或者 b 还没有发生改变,多次访问 count 计算属性会立即返回之前的计算结果,而不必再次执行函数。

  相比之下,每当触发重新渲染时,调用方法将总会再次执行函数,

  我们为什么需要缓存? 假设我们有一个性能开销比较大的计算属性 A,他需要遍历一个巨大的数组并做大量的计算,然后我们可能有其他的计算属性依赖于 A。如果没有缓存我们将不可避免的多次执行 A 的getter。如果不希望有缓存出现,请用方法代替。

  计算属性的 setter

  计算属性默认只有 getter ,不过在需要时也可以提供一个 setter

  computed: {
    str: {
      get: function() {
        return this.a + this.b
      },
      set: function(newVlaue) {
        var abs = newValue.split(‘ ‘)
        this.a = abs[0]
        this.b = abs[abs.length - 1]
      }
    }
  }

  现在运行 this.str = ‘2 3 4 5‘时,setter 会被调用,this.a 和 this.b 也会相应地被更新

  

5.methods 事件处理

  在模板中通过 v-on 定义方法名,在 methods 中定义方法

  有时在内联语句处理器中访问原始的 DOM 事件,可以用特殊变量 $event 把它传入方法

<button @click="count(200, $event)">按钮</button>
<button @click="count2">按钮2</button>
  methods: {
    count: function(val, event) {
      if(event) {
        event.preventDefault()
      }
      // ...
    },
    count2: function(event) {// 如果模板中什么都不传递,在这里可以默认直接接受一个参数就是 dom 对象
      if(event) {
        event.preventDefault()
      }
      // ...
    }
  }

  

6.watch 监听器

  一个对象,键是需要观察的表达式,值是对应回调函数,值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性

  值是包括选项的对象,有三个选项

  handler:回调函数,即监听到变化时应该执行的函数

  deep: Boolean,确认是否深度监听

    为了发现对象内部值的变化,可以在选项参数中指定 deep: true 注意监听数组的变更不需要这么做

  immediate:Boolean,为true时,将立即以表达式的当前值出发回调(进入页面就开始监听)

  watch: {
    a(){},
    // 该回调会在任何被监听的对象 property 改变时被调用,不论其被嵌套多深
    b: {
      handler: function(){},
      deep: true
    },
    // 该回调将会在侦听开始之后立即调用
    c: {
      handler: function(),
      immediate: true
    },
    // 可以传入回调数组,他们会被一一调用
    d: [
      handle1,
      function handle2(){},
      {
        handler: function handle3(){}
      }
    ]
  }

 

二、选项 / DOM

在开发的过程中很少需要考虑这些东西,看看官网熟悉一下

  到官网去了解一下

  

 三、选项 / 生命周期钩子

  每个 Vue 实例在被创建时都要经过一系列的初始化过程,设置数据监听,编译模板,实例挂载到 DOM ,数据变化时更新 DOM 等,这里面有一系列的函数,称之为生命周期钩子

1.beforeCreate

  在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用,此时组件的选项对象还没有创建,el 和 data 并未初始化,因此无法访问 methods,data,computed 等上的方法和数据

 

2.created

  在实例创建完成之后被立即调用。这一步,实例已经完成以下配置:数据观测(data observer),property 和方法的运算,watch/event 事件回调。然而挂载阶段还没开始,$el property 目前尚不可用。这是一个常用的生命周期,这里面可以调用 methods 中的方法,改变 data 中的数据,并且修改可以通过 vue 的响应式绑定体现在页面上,获取 计算属性 等等,通常我们在这里请求接口中的数据,

 

3.beforeMount

  在挂在之前被调用,相关的 render 函数首次被调用,实例已经完成一下的配置:编译模板,把 data 里面的数据和模板生成 html,完成了 el 和 data 初始化,注意此时还没有挂载到 html 页面上

 

4.mounted

  实例被挂载后被调用,这时 el 被新创建的 vm.$el 替换了。如果跟实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内

  注意 mounted 不会保证所有的子组件也一起被挂载,如果希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick 

  mounted(){
    this.$nextTick(function(){
      // ...
    })
  }

 

5.beforeUpdate

  数据更新时调用,发生在虚拟 DOM 打补丁之前,这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行

 

6.updated

  由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

  当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用 计算属性 或 watcher 取而代之。

  注意 updated 不会保证所有子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick(同上)

 

 7.activated

  被 keep-alive 缓存的组件激活时调用

  该钩子在服务器端渲染期间不被调用

 

8.deactivated

  被 keep-alive 缓存的组件停用时被调用

  该钩子在服务器端渲染期间不被调用

 

9.beforeDestroy

  实例销毁之前调用。在这一步,实例仍然完全可用

  该钩子在服务器端渲染期间不被调用

 

10.destroyed

  实例销毁后调用,该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁

  该钩子在服务器端渲染期间不被调用

 

11.errorCaptured

  当捕获一个来自子孙组件的错误时被调用,此钩子会收到三个参数:错误对象、发生错误的组件实例和一个包含错误来源信息的字符串。此钩子返回 false 以阻止该错误继续向上传播

  可以在此钩子中修改组件的状态。因此在捕获错误时,在模板或渲染函数中有一个条件判断来绕过其他内容就很重要,不然该组件可能会进入一个无限的渲染循环

  错误传播规则

    1.默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。

    2.如果一个组建的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误一一唤起

    3.如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 config.errorHandler

    4.一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说’这个错误已经被搞定且应该被忽略‘。他会阻止其他任何会被这个错误唤起的 errorCaptured 钩子和全局的 config.errorHandler

 

四、选项 / 资源

1.directives 自定义指令

2.filters 过滤器

3.components 组件

  directives、filters、components 详情在这里有介绍 vue API 知识点(1)---全局 API 总结

 

五、选项 / 组合

1.parent

  指定已创建的实例之父示例,在两者之间建立父子关系。子实例可以用 this.$parent 访问父实例,子实例被推入到父实例的 $children 数组中

  我们在开发中,基本上不会使用到 $parent 和 $children 。更多的是使用 props 和 events 实现父子组件通信,

 

2.mixins 混入

3.extends

  允许声明扩展另一个组件,而无需使用 Vue.extend。这主要是为了便于扩展单文件组件

  这和 mixins 有点类似 

  mixins、extends 在这篇文章中有详细的介绍  vue API 知识点(1)---全局 API 总结

 

4.provide / inject 

  provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

  这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

  解析:就是组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,可以不使用 props 的方式依次传递给子孙组件,层次太多,代码结构容易混乱。那么就可以使用 provide/inject 来做传递

  官方注解

  provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 Symbols 作为key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作

  inject 选项应该是一个字符串数组或一个对象,对象的key是本地的绑定名,

    value 是 在可用的注入内容中搜索用的 key(字符串或 Symbol),或一个对象,该对象的

      from property 是在可用的诸如内容中搜索用的 key(字符串或 Symbol)

       default property 是降级情况下使用的 value

  个人解析

  provide 是一个对象,或者是一个返回对象的函数,里面就包含要给子孙后代的东西,也就是属性和属性值

  inject 一个字符串数组,或者是一个对象。属性值可以是一个对象,包含 from 和 default 默认值

  const Child = {
    inject: {
      foo: {
        from: ‘bar‘,
        default: ‘foo‘
      }
    }
  }

    from 表示在可用的注入内容中搜索用的 key,default 当然就是默认值

   注意:provide 和 inject 绑定并不是可响应的。这是刻意为之的,然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的

   官方示例

   // 父组件
  var Provider = {
    provide: {
      name: ‘zhangning‘
    },
    // ...
  }

  // 子组件注入
  var Child = {
    inject: [‘name‘],
    created() {
      console.log(this.name) // => ‘zhangning‘
    }
  }

  利用 es 中的 Symbols、函数 provide 和对象 inject

  const a = Symbol();
  const Parent = {
    provide(){
      return {
        [a]: ‘zhangning187‘
      }
    }
  }

  const Child = {
    inject: { a },
    // ...
  }

  在新版本中,使用一个注入的值作为一个 property 的默认值

  const Child = {
    inject: [‘name‘],
    props: {
      bar: {
        default() {
          return this.name
        }
      }
    }
  }

  使用一个注入的值作为数据入口

  const Child = {
    inject: [‘name‘],
    data() {
      return {
        bar: this.name
      }
    }
  }

  如果它需要从一个不同名字的 property 注入,则使用 from 来表示其源 property

  const Child = {
    inject: {
      from: ‘bar‘,
      default: ‘name‘
    }
  }

  与 prop 的默认值类似,你需要对非原始值使用一个工厂方法

  const Child = {
    inject: {
      name: {
        from: ‘bar‘,
        default: () => [1, 2, 3]
      }
    }
  }

   在日常的开发中,我们经常会使用 Vuex 做状态管理,但是 vuex 有时候太过于繁琐。如果我们不想使用 vuex,这个时候我们就可以使用 provide/inject 这个方式来代替vuex,在跟组件中传入变量,然后在后代组件中使用即可

  // 在跟组件中提供一个非响应式变量给后代组件

  export default {
    provide() {
      return {
        text: ‘zhangning‘
      }
    }
  }

  // 后代组件注入 
  export default {
    inject: [‘text‘],
    created() {
      this.text = ‘zhangning187‘// 在我们使用 text 的时候它依然是 zhangning,而不是zhangning187
    }
  }

  上面已经讲过,provide 和 inject 绑定并不是可响应的,这是可以为之。当然我们也可以传入一个可响应的对象,那么它的属性也就是可响应的了

  也就是说,Vue 不会对 provide 中的变量进行响应式处理。所以要想 inject 接受的变量是响应式的,provide 提供的变量本身就需要是响应式的。

  由于组件内部的各种状态就是可响应式的,所以我们直接在根组件中将组件本身注入 provide,此时,我们可以在后代组件中任意访问根组件中的所有状态,根组件就成为了全局状态的容器

  // 根组件提供将自身提供给后代组件
  export default {
    provide() {
      return {
        app: this
      }
    },
    data() {
      return {
        text: ‘zhangning‘
      }
    }
  }

  // 后代组件 注入

  export default {
    inject: [‘app‘],
    data(){
      return{}
    },
    created: {
      this.app.text = ‘zhangning187‘// 此时使用 text,它的值就是zhangning187
    }
  }

  当然,我们也可以通过 $root 来获取根节点,但是在团队开发的过程中,如果所有的全局变量都统一定义在根组件中并不合适,而使用 provide/inject 不同模块的入口组件传给各自的后代组件可以完美解决这个问题

  Vuex 和 provide/inject 区别在于,Vuex 中的全局状态的每次修改都是可以追踪回溯的,而 provide/inject 中变量的修改是无法控制的,通俗说就是,你不知道是哪个组件修改了这个全局状态。

  provide/inject 破坏了我们的单向数据流原则。如果多个后代组件同时依赖于一个祖先组件提供的状态,那么只要有一个组件修改了这个状态,则所有组件都会受到影响。这个使耦合度增加了,让我们的数据变化不可控,在多人的开发过程中,这个可能会变得特别混乱。

  以上看起来使用 provide/inject 做全局状态管理好像很危险,所以我们要谨慎使用这个方式。

  但是在组件开发的时候,vue 官方提倡我们使用这种方法。例如 elment-ui 

 

六、选项 / 其他

1.name

  只有作为组件选项时起作用

  允许组件模板递归地调用自身,注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name

  指定 name 选项的好处就是便于调试,有名字的组件有更友好的警告信息,当在 vue-devtools 下,未命名组件将显示成<AnonymousComponent>,这很没有语义,通过提供 name 选项,可以获得更有语义信息的组件树

 

2.delimiters

  了解一下就行,通常不会去更改插入分隔符

  类型 Array<string>

  默认值 ["{{", "}}"]

  限制 这个选项只在完整构建版本中的浏览器内编译时可用

  改变纯文本插入分隔符

  示例

  new Vue({
    delimiters: ["${", "}"]
  })
  // 分隔符变成了 ES6 模板字符串的风格

 

3.functional

  了解一下,通常用不到

  类型 Boolean

  使组件组状态(没有 data)和无实例(没有 this 上下文)。他们用一个简单的 render 函数返回虚拟节点,是他们渲染的代价更小

 

4.model

  允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一下输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突

  // 定义一个组件

  Vue.component(‘my-check‘, {
    model: {
      prop: ‘checked‘,
      event: ‘change‘
    },
    props: {
      value: String,
      checked: {
        type: Number,
        default: 0
      }
    }
  })

  使用

  <my-check v-model=‘foo‘ value=‘some value‘></my-check>

  以上代码相当于

  <my-check :checked=‘foo‘ @change=‘value=>{foo = val}‘ value=‘some value‘></my-check>

  

  我们先了解一下 input 中的 v-model 是怎么实现双向绑定的。

  <input type=‘text‘ v-model=‘msg‘>

  v-model 只是语法糖真正的实现方式

  <input type=‘text‘ :value=‘msg‘ @input=‘msg=$event.target.value‘>

  真正的双向绑定是通过监听 input 事件

    v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件

    text 和 textarea 元素使用 value 属性和 input 事件

    checkbox 和 radio 使用 checked 属性和 change 事件

    select 使用 value 和 change 事件

  我们可以自定义输入框组件的 v-model,双向绑定

  Vue.component(‘my-input‘, {
    template: `<input :value=‘value‘ @input=‘updateValue($event.target.value)‘ type=‘text‘></input>`,
    props: [‘value‘],
    methods: {
      updateValue(val) {
        this.$emit(‘input‘, val)
      }
    }
  })

  let app = new Vue({
    el: ‘#app‘,
    data(){
      message: ‘‘
    },
    methods: {
      handleInput(val) {
        this.message = val
      }
    }
  })
  <div id=‘app‘>
    <my-input :value=‘message‘ @input=‘handleInput‘></my-input>
  </div>

  上面的示例我们可以了解到,默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,所以当我们在一个自定义组件上使用 v-model 并不能实现双向绑定,因为自定义的组件并没有默认的 value 和 input 事件,在使用时,我们需要按照上面那样显式的去声明定义这些东西,这时,选项 model 就派上用场了,在定义组件的时候指定 prop 的值和监听的事件(看到这里,上面写的官网给出的例子也应该可以看明白了)

  举例

  Vue.component(‘my-input‘, {
    model: {
      prop: ‘uname‘,
      event: ‘handleChange‘
    },
    props: {
      uname: {
        type: String,
        default: ‘zhangning‘
      }
    },
    methods: {
      updateVal(val) {
        this.$emit(‘handleChange‘, val)
      }
    }
  })

  模板

  <template>
    <div>
      <input type=‘text‘ :value=‘uname‘ @input=‘updateVal($event.target.value)‘>
    </div>
  </template>

  使用组件

  <my-input v-model=‘name‘ value=‘some value‘></my-input>

  等价于

   <my-input :uname=‘name‘ @handleChange=‘val=>{foo = val}‘ value=‘some value‘></my-input>

  上面的示例中我们就可以在自定义的组件中使用 v-model 来进行双向绑定了(多看一下示例就明白了)

 

vue API 知识点(2)---选项总结

上一篇:如何在PS中制作虚线?PS制作虚线的两种方法介绍


下一篇:【电子取证:镜像仿真篇】Windows Server镜像仿真、vmdk镜像仿真