作者:saucxs | songEagle 来源:原创
这个题目本身不是特别难,只能说是作为社招的基础面试题,但是如果想回答好这道题也不是很容易。
不信接着往下看
vue.js是一个非常优秀的前端开发框架,使用vue的版本是v2.x
vue几个核心的地方:vue实例化,虚拟DOM,模板编译过程,数据绑定。
我们开始回到正题,vue.js的作者尤雨溪最初就是尝试实现一个类似angular1的东西,发现里面对于数据处理非常不优雅,于是创造性的尝试利用ES5中的Object.defineProperty来实现数据绑定,于是就有了最初的vue。
vue的数据绑定的实现原理离不开vue中响应式的数据处理方式。
我们可以回想一下官网的图:
vue的响应式基本原理:
概括回答我们只回答了使用ES5的方法 Object.defineProperty 实现数据的监听的,那么具体是如何实现还是没有讲的很清楚。
这时候我们需要问自己,如何找亮点?
vue的响应式原理设计三个重要对象:Observer,Watcher,Dep。
当属性变化会执行主题对象Observer的dep.notify方法, 这个方法会遍历订阅者Watcher列表向其发送消息, Watcher会执行run方法去更新视图。
依赖关系图如下,更能方面我们的理解
接着我们需要补充的是:模板编译过程中的指令和数据绑定都会生成Watcher实例,实例中的watch属性也会生成Watcher实例。
说的这些有没有觉得有点乱,那我们总结一下如何亮点回答
然后写一个使用Object.defineProperty实现监听变量
var obj = {};
var a;
Object.defineProperty(obj, 'a', {
get: function() {
console.log('get val');
return a;
},
set: function(newVal) {
console.log('set val:' + newVal);
a = newVal;
}
});
obj.a; // get val
obj.a = 'saucxs' //set val
如果上面代码格式出现问题,可以查看下面代码图片
因为现在vue已经到3了,不再是停留在2的时候,这个时候,可以把3的原理简单说一下。
这个时候不应该是ES6的proxy特性上场了,proxy是ES6的新增的功能,可以用来定义对象中的操作。
let p = new Proxy(target, handler);
// `target` 代表需要添加代理的对象
// `handler` 用来自定义对象中的操作
如果上面代码格式出现问题,可以查看下面代码图片
可以很方便的使用 Proxy 来实现一个数据绑定和监听.
let onWatch = (obj, setBind, getLogger) => {
let handler = {
get(target, property, receiver) {
getLogger(target, property)
return Reflect.get(target, property, receiver);
},
set(target, property, value, receiver) {
setBind(value);
return Reflect.set(target, property, value);
}
};
return new Proxy(obj, handler);
};
let obj = { saucxs: 1 }
let value
let p = onWatch(obj, (v) => {
value = v
}, (target, property) => {
console.log(`Get '${property}' = ${target[property]}`);
})
p.saucxs = songEagle // bind `value` to `songEagle`
p.saucxs // -> Get 'saucxs' = songEagle
如果上面代码格式出现问题,可以查看下面代码图片
然后在对比vue2和vue3的区别是什么?
以及为啥在数据监听上做了升级?
vue为什么对数组对象的深层监听无法实现,因为组件每次渲染都是将data里的数据通过defineProperty进行响应式或者双向绑定上,之前没有后加的属性是不会被绑定上,也就不会触发更新渲染。
区别:
1、语法层面上
2、兼容层面上