1、简述vue2.0+的基本原理
延伸:
vue2 | vue3 |
---|---|
defineProperty | proxy |
需要做递归去添加对象每个属性的setter和getter | 可以直接监听对象的变化 |
需要对数组操作做单独适配 | 兼容性不好 |
2、vue的生命周期
3、vuex的原理
参考这篇文章 https://www.jianshu.com/p/d95a7b8afa06
写的很清晰,也容易理解。
4、vue父子组件通信
参考下面的文章:
https://blog.csdn.net/wy6250000/article/details/83793400
5、vue eventbus
看看源码:
Vue.prototype.$on = function (event, fn) {
var vm = this;
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
vm.$on(event[i], fn);
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn);
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
if (hookRE.test(event)) {
vm._hasHookEvent = true;
}
}
return vm
};
把方法添加到对应的事件队列
Vue.prototype.$emit = function (event) {
var vm = this;
{
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
var info = "event handler for \"" + event + "\"";
for (var i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info);
}
}
return vm
};
emit触发的时候,找到对应的event队列,去挨个调用里面的fn
6、vue中对数组是如何劫持的
因为defineProperty只能劫持对象的getter和setter,所以vue在对数组的操作中做了以下处理,利用修改Array.prototype, 对数组各个操作方法加上notify()去通知watcher用以更新视图。
const arrayProto = Array.prototype//原生Array的原型
export const arrayMethods = Object.create(arrayProto);
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
].forEach(function (method) {
const original = arrayProto[method]//缓存元素数组原型
//这里重写了数组的几个原型方法
def(arrayMethods, method, function mutator () {
//这里备份一份参数应该是从性能方面的考虑
let i = arguments.length
const args = new Array(i)
while (i--) {
args[i] = arguments[i]
}
const result = original.apply(this, args)//原始方法求值
const ob = this.__ob__//这里this.__ob__指向的是数据的Observer
let inserted
switch (method) {
case 'push':
inserted = args
break
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) ob.observeArray(inserted)
// notify change
ob.dep.notify()
return result
})
})
//定义属性
function def (obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
});
}