}
vnode.data.keepAlive = true; //标记虚拟节点已经被缓存
}
// 返回虚拟节点
return vnode || (slot && slot[0]);
},
};
4.Vue.set 方法原理
了解 Vue 响应式原理的同学都知道在两种情况下修改数据 Vue 是不会触发视图更新的
1.在实例创建之后添加新的属性到实例上(给响应式对象新增属性)
2.直接更改数组下标来修改数组的值
Vue.set 或者说是$set 原理如下
因为响应式数据 我们给对象和数组本身都增加了__ob__属性,代表的是 Observer 实例。当给对象新增不存在的属性 首先会把新的属性进行响应式跟踪 然后会触发对象__ob__的 dep 收集到的 watcher 去更新,当修改数组索引时我们调用数组本身的 splice 方法去更新数组
相关代码如下
export function set(target: Array | Object, key: any, val: any): any {
// 如果是数组 调用我们重写的splice方法 (这样可以更新视图)
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val;
}
// 如果是对象本身的属性,则直接添加即可
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).ob;
// 如果不是响应式的也不需要将其定义成响应式属性
if (!ob) {
target[key] = val;
return val;
}
// 将属性定义成响应式的
defineReactive(ob.value, key, val);
// 通知视图更新
ob.dep.notify();
return val;
}
5.Vue.extend 作用和原理
官方解释:Vue.extend 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
其实就是一个子类构造器 是 Vue 组件的核心 api 实现思路就是使用原型继承的方法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并
相关代码如下
export default function initExtend(Vue) {
let cid = 0; //组件的唯一标识
// 创建子类继承Vue父类 便于属性扩展
Vue.extend = function (extendOptions) {
// 创建子类的构造函数 并且调用初始化方法
const Sub = function VueComponent(options) {
this._init(options); //调用Vue初始化方法
};
Sub.cid = cid++;
Sub.prototype = Object.create(this.prototype); // 子类原型指向父类
Sub.prototype.constructor = Sub; //constructor指向自己
Sub.options = mergeOptions(this.options, extendOptions); //合并自己的options和父类的options
return Sub;
};
}
Vue 组件原理详解 传送门
6.写过自定义指令吗 原理是什么
指令本质上是装饰器,是 vue 对 HTML 元素的扩展,给 HTML 元素增加自定义功能。vue 编译 DOM 时,会找到指令对象,执行指令的相关方法。
自定义指令有五个生命周期(也叫钩子函数),分别是 bind、inserted、update、componentUpdated、unbind
-
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
-
inserted:被绑定元素插入父节点时调用