美文网首页VueJS
VueJS学习之旅 07

VueJS学习之旅 07

作者: 小A家的铭 | 来源:发表于2017-01-19 18:55 被阅读1133次

    下面我就来看看Vue的核心构造器以及其实例的属性和方法。


    Vue构造器

    从 'src/core/index.js' 文件中可以找到Vue构造器的定义是在 'src/core/instance/index.js' 中给出的。
    打开该文件,我们来看看代码。

    // src/core/instance/index.js
    
    import { initMixin } from './init'
    import { stateMixin } from './state'
    import { renderMixin } from './render'
    import { eventsMixin } from './events'
    import { lifecycleMixin } from './lifecycle'
    import { warn } from '../util/index'
    
    function Vue (options) {
      if (process.env.NODE_ENV !== 'production' &&
        !(this instanceof Vue)) {
        warn('Vue is a constructor and should be called with the `new` keyword')
      }
      this._init(options)
    }
    
    initMixin(Vue)
    stateMixin(Vue)
    eventsMixin(Vue)
    lifecycleMixin(Vue)
    renderMixin(Vue)
    
    • 非常简短,该构造器接收一个对象类型的 options 参数。
    • 初始化Vue实例对象时,默认调用原型对象上的 _init (Vue.prototype._init) 方法。

    该文件中还通过调用一些模块,给Vue增加了一些实例方法。

    • 与数据相关的方法:$set, $delete, $watch
    • 与事件相关的方法:$on, $once, $off, $emit
    • 与生命周期相关的方法:$forceUpdate, $destroy
    • 还有一个与生命周期相关的方法 $mount 是在entiry文件(如: 'src/entries/web-runtime-with-compiler.js')中定义的。

    以上的这些方法,就是对应官方API中实例方法。

    Vue实例对象方法

    结合官方API文档和源码,具体来看看这些实例方法。

    实例方法 / 数据相关

    • vm.$watch

      对应方法源码 src/core/instance/state.js => Vue.prototype.$watch

      1. 该方法内部新建一个Watcher实例,并将其添加到当前Vue实例对象的 _watchers 列表中。
      2. 方法返回值是一个撤销观察函数 unwatch。如需撤销观察,只需执行 unwatch();
    • vm.$set

      对应方法源码 src/core/instance/state.js => Vue.prototype.$set

      1. 从代码可见,这是Global API中 Vue.set 的别名。
    • vm.$delete

      对应方法源码 src/core/instance/state.js => Vue.prototype.$delete

      1. 从代码可见,这是Global API中 Vue.delete 的别名。

    实例方法 / 事件相关

    • vm.$on

      对应方法源码 src/core/instance/events.js => Vue.prototype.$on

      1. Vue实例对象 vm 中有 _events 属性,用来记录事件的注册信息
      2. 如果 vm 中已有 event 事件注册过,则向该事件注册列表中添加callback处理器;如果没有相关事件注册过,则先行初始化该事件注册列表,再将callback注册到列表中。
      3. 如果 event 是 hook 事件,则将 vm_hasHookEvent 属性设置为 true
      4. 执行结果返回 vm
    • vm.$off

      对应方法源码 src/core/instance/events.js => Vue.prototype.$off

      1. 如果没有传递参数,默认将 vm_events 清空,然后返回当前实例对象。相当于注销所有事件注册。
      2. 如果 vm 还没有注册过 event 事件,直接返回 vm
      3. 如果只提供了 event,则移除该事件所有的监听器
      4. 如果同时提供了 eventcallback,则获取该 event 的注册列表,遍历列表将给定的 callback 监听器注销。
    • vm.$once

      对应方法源码 src/core/instance/events.js => Vue.prototype.$once

      1. 分别调用 $on$off 来完成事件的注册和注销。
      2. 只执行一次,执行后立即移除监听器。
    • vm.$emit

      对应方法源码 src/core/instance/events.js => Vue.prototype.$emit

      1. 获取 vmevent 的注册列表
      2. 遍历注册列表中的所有处理器,依次调用

    实例方法 / 生命周期相关

    • vm.$forceUpdate

      对应方法源码 src/core/instance/lifecycle.js => Vue.prototype.$forceUpdate

      1. 如果当前实例对象存在 _watcher 属性,执行 _watcherupdate 方法。
    • vm.$destroy

      对应方法源码 src/core/instance/lifecycle.js => Vue.prototype.$destroy

      1. Vue实例对象 vm 如果被标记为正在销毁(_isBeingDestroyed == true),则直接返回,避免重复调用。
      2. 调用 'beforeDestroyed' 生命周期事件处理函数。
      3. _isBeingDestroyed 属性标记为 true。
      4. 清除父对象中的信息
      5. 清除watchers
      6. 清除当前对象的数据监听(observer)
      7. 调用 'destroyed' 生命周期事件处理函数。
      8. 清除所有注册的事件监听
      9. 触发视图更新
    • vm.$nextTick

      对应方法源码 src/core/instance/render.js => Vue.prototype.$nextTick

      1. 代码执行与 Vue.nextTick 一样,只不过方法执行的句柄(this)自动邦定到当前的Vue实例对象。
    • vm.$mount

      对应方法源码 src/entries/web-runtime-with-compiler.js => Vue.prototype.$mount

      1. 该方法实际上调用的是 Vue.prototype._mount 方法,定义在 'src/core/instance/lifecycle.js' 文件中。
      2. 如果实例对象 vm 中没有给定 render ,则将 'createEmptyVNode' 赋值给 'render'。
      3. 调用 'beforeMount' 生命周期事件处理函数。
      4. vm 增加watcher。
      5. 调用 'mounted' 生命周期事件处理函数。
      6. 返回 vm 实例对象。

    Vue对象实例的属性

    有关于Vue实例属性的初始化,基本上是调用 Vue.prototype._init 方法中完成的。上面提到过这个方法会在new Vue(options) 时自动调用。
    这个方法定义在 'src/core/instance/init.js' 文件中,简要地看看它都做了什么。

    1. 初始化 vm.$options,主要是调用 mergeOptions 方法,将构造器的默认属性与给定的options合并后赋值为 vm.$options
    2. 初始化生命周期相关的属性,给 vm.$parent, vm.$root, vm.$children, vm.$refs 等属性赋值。
    3. 初始化 vm 事件监听,将父组件事件更新到当前对象
    4. 调用 'beforeCreate' 生命周期事件处理函数
    5. 初始化与data相关的属性,这里面有一步重要的操作,就是observe数据(vm._data,vm.$data就是对该对象的代理)。这会创建Observer对象并调用 defineReactive 函数,这是Vue实现双向数据邦定的基础。具体请参照 defineReactive 函数以及JS属性描述符相关资料。
    6. 调用 'created' 生命周期事件处理函数
    7. 初始化 render 相关的属性:$slots, $scopedSlots等。

    结合官方API文档和源码,具体来看看这些实例属性的含义以及他们是如何赋初值的。

    • vm.$data

      Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。

      1. 该属性不是直接定义在实例对象 vm 上,而是定义在原型对象上 => Vue.prototype.$data
      2. 该属性是只读属性,不能直接给该属性重新赋值。但可以set其内部具体的内嵌属性。
      3. 个人理解,就是应为要定义为只读属性,所以在定义在prototype对象上。
    • vm.$el

      Vue 实例使用的根 DOM 元素。

      1. 该属性不是在初始化时设置的,而是在调用 Vue.prototype._mountue.prototype._update 时才赋值的。
    • vm.$options

      用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。构造器的默认属性与给定的options合并后赋值给它。
    • vm.$parent

      父实例,如果当前实例有的话。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$root

      当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自已。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$children

      当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$slots

      用来访问被 slot 分发的内容。每个具名 slot 有其相应的属性(例如:slot="foo" 中的内容将会在 vm.$slots.foo 中被找到)。default 属性包括了所有没有被包含在具名 slot 中的节点。
      在使用 render 函数书写一个组件时,访问 vm.$slots 最有帮助。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$scopedSlots

      用来访问被 scoped slots。包括 default 在内的每个 slot,对象内都包含一个返回 VNodes 的函数。
      在使用 render 函数书写一个组件时,访问 vm.$slots 最有帮助。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$refs

      一个对象,其中包含了所有拥有 ref 注册的子组件。

      1. 当初始化实例对象时,通过执行 Vue.prototype._init 方法时赋值的。
    • vm.$isServer

      当前 Vue 实例是否运行于服务器。

      1. 该属性不是直接定义在实例对象 vm 上,而是定义在原型对象上 => Vue.prototype.$isServer
      2. 该属性根据当前运行的环境以及 process.ven.VUE_ENV 自动设置。

    相关文章

      网友评论

        本文标题:VueJS学习之旅 07

        本文链接:https://www.haomeiwen.com/subject/kggmbttx.html