vm.$forceUpdate
这个api的作用是使vue实例重新渲染。
Vue.prototype.$forceUpdate = function () {
var vm = this;
if (vm._watcher) {
vm._watcher.update();
}
};
以上代码,先拿到vue实例自身。如果vue实例对应的那个watcher存在的话,就调用其更新API。(Vue2.0开始采用中等粒度的设计思路,将一个组件映射到一个watcher)
vm.$destroy
这个api的作用是销毁vue实例
Vue.prototype.$destroy = function () {
var vm = this;
if (vm._isBeingDestroyed) {
return
}
callHook(vm, 'beforeDestroy');
vm._isBeingDestroyed = true;
// remove self from parent
var parent = vm.$parent;
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
remove(parent.$children, vm);
}
// teardown watchers
if (vm._watcher) {
vm._watcher.teardown();
}
var i = vm._watchers.length;
while (i--) {
vm._watchers[i].teardown();
}
// remove reference from data ob
// frozen object may not have observer.
if (vm._data.__ob__) {
vm._data.__ob__.vmCount--;
}
// call the last hook...
vm._isDestroyed = true;
// invoke destroy hooks on current rendered tree
vm.__patch__(vm._vnode, null);
// fire destroyed hook
callHook(vm, 'destroyed');
// turn off all instance listeners.
vm.$off();
// remove __vue__ reference
if (vm.$el) {
vm.$el.__vue__ = null;
}
// release circular reference (#6759)
if (vm.$vnode) {
vm.$vnode.parent = null;
}
};
首先拿到vue实例本身。
1.根据vue实例的_isBeingDestroyed判断vue实例是否正在被销毁。正在被销毁直接返回。(我的理解是可能存在同一时间段内,都触发了销毁逻辑的情况)
2.之后调用callHook函数触发vue实例销毁之前的那个钩子函数。将vue实例的_isBeingDestroyed打上正在被销毁的标记。
3.拿到此组件的父组件。然后判断此父组件存不存在,是否被销毁,是否是抽象组件(即是否是transition、keep-alive等组件)。如果父组件存在,并且没被销毁,又不是抽象组件,直接从它保存子组件的数组中移除该vue实例。
4.判断组件是否对应一个watcher,如果有watcher直接清除它所监听的所有状态。
5.之后通过while循环清除用户自己定义的watcher。
6.将对应数据观测者的数量减一。
7.将vue实例的_isDestroyed属性打上标记。表明此vue实例已被销毁。
8.将对应的虚拟树和其对应的dom结构销毁。
9.之后调用callHook函数触发vue实例销毁后的那个钩子函数。
10.移除所有事件监听器。
11.如果vue有挂载的元素,将其对应的vue实例置空。
12.之后去判断此vue对应的虚拟dom树,如果存在,将它的父节点置空。
如果有错,请大佬指出。