关注“松宝写代码”,精选好文,每天一题时间永远属于自己,分分秒秒也为你的未来增值作者:saucxs|songEagle来源:原创1.前言文章于2020年12月23日首发wx《松宝写代码》flag,每日一题。题型不限,可以是:算法题、面试题、阐述题等。本文为“每日一题”第5题:如何回答“每日一题”:vue数据绑定的实现原理?上一篇《每日一问》:第四期《每日一问》与面试官的手撕代码:如何科学高效的寻找重复元素?第三题《每日一题》面试官问你对Promise的理解?可能是你需要能够手动实现每一个特性。第二轨【《【每日一问】ES6为什么要用Symbol?】】(https://mp.weixin.qq.com/s/om...1.《一道面试题如何引发心灵深处的拷问?》2.vue数据绑定的实现原理?这道题本身并没有特别难,只能说是一道社招的基础面试题,但是想要很好的回答这道题就不是很容易了。如果不信你往下看1.总答Vue.js是一个非常好的前端开发框架,使用vue的版本是v2.xvue的核心:vue实例化,虚拟DOM,Template编译过程,数据言归正传,vue.js的作者游玉玺最初尝试实现类似angular1的东西,发现对于数据处理不是很优雅,于是创造性地尝试使用ES5中的Object。defineProperty实现数据绑定,于是就有了原来的vue.vue的数据绑定的实现原理离不开fromvue中的响应式数据处理方式。我们可以回忆一下官网上的图:vue响应式的基本原理:1.Vue会遍历这个数据中对象的所有属性,2.使用Object.defineProperty将这些属性全部转化为getters/setters,3.每个组件实例都有一个watcher对象,4。它会在组件5中被渲染。后面调用依赖的setter时,会通知watcher重新计算,从而导致其关联的组件更新。2.HighlightsResponsesGeneralResponses我们只回答了使用ES5方法Object.defineProperty来实现数据监控,具体如何实现还不清楚。这时候,我们就需要扪心自问,如何寻找亮点?Vue的响应式原则设计了三个重要的对象:Observer、Watcher和Dep。观察者对象:vue中的数据对象在初始化的时候会转化为观察者对象。Watcher对象:结合模板和Observer对象生成Watcher实例,Watcher是订阅者中的订阅者。Dep对象:Watcher对象和Observer对象之间的联系,每个Observer都有一个Dep实例,用于存放订阅者Watcher。当属性发生变化时,会执行subject对象Observer的dep.notify方法。该方法会遍历订阅者Watcher列表向其发送消息,Watcher会执行run方法更新视图。依赖图如下,可以更好的理解我们的理解。然后需要补充一点:模板编译过程中的指令和数据绑定会生成Watcher实例,实例中的watch属性也会生成Watcher实例。是不是感觉说的有点乱,那我们总结一下如何突出答案1、在生命周期的initState方法中,劫持data、prop、method、computed、watch中的数据,使用observe方法进行关联用Object.defineProperty方法将对象转换为Observer对象。2.然后在initRender方法中解析模板,通过Watcher对象、Dep对象和观察者模式,建立模板中指令与对象数据的依赖关系,使用全局对象Dep.target实现依赖集合。3.当数据发生变化时,调用setter,触发Object.defineProperty方法中的dep.notify方法,遍历数据依赖列表,executorupdate方法通知Watcher更新视图。Vue无法检测对象属性的增删改查,但是可以使用全局的Vue.set方法(或者vm.$set实例方法)。Vue无法检测到使用索引设置数组,但是可以使用全局的Vue.set方法(或者vm.$set实例方法)。无法检测并直接修改数组的长度,但是可以使用splice,然后使用Object.defineProperty写一个监控变量varobj={};vara;Object.defineProperty(obj,'a',{get:function(){console.log('getval'); returna;},set:function(newVal){console.log('setval:'+newVal);a=newVal;}});obj.a;//getvalobj.a='saucxs'//setval如果上面的代码格式有问题,可以查看下面的代码图。3.进阶回答因为vue现在已经到了3了,不再是2了,这个时候可以简单说明一下3的原理,这个时候应该不是ES6的proxy特性。Proxy是ES6的一个新功能,可以用来定义对象中的操作。letp=newProxy(target,handler);//`target`表示需要添加代理的对象//`handler`用于自定义对象中的操作如果上面的代码格式有问题,方便可以看下面的代码图使用Proxy实现数据绑定和监控。)returnReflect.get(目标,属性,接收者);},set(target,property,value,receiver){setBind(value);返回Reflect.set(目标,属性,值);}};returnnewProxy(obj,handler);};letobj={saucxs:1}letvalueletp=onWatch(obj,(v)=>{value=v},(target,property)=>{console.log(`Get'${property}'=${target[property]}`);})p.saucxs=songEagle//将`value`绑定到`songEagle`p.saucxs//->Get'saucxs'=songEagleIf上面的代码格式有问题,可以查看下面的代码图片然后vue2和vue3有什么区别?为什么要升级数据监控?为什么不能实现vue对数组对象的深度监控,因为每次组件渲染时,data中的数据都是通过defineProperty响应式或双向绑定的,之前没有添加的属性不会绑定,即不触发更新渲染。不同点:1.在语法层面上,defineProperty只能在第一次渲染时响应属性。Proxy需要的是全局监控,不需要关心里面的任何属性,而且Proxy里面有13个配置项,可以做更细化的事情。这是之前的defineProperty无法到达。2、兼容性层面,vue2.x之所以只能兼容IE8,是因为defineProperty无法兼容IE8,其他浏览器也会有轻微的兼容性问题。除了IE,proxy还兼容其他浏览器。这次vue3还是用了,也就是说vue3直接放弃了IE兼容的考虑。各种福利《松宝写代码》:开发知识体系搭建、技术分享、项目实践、实验室,每天一题,带你一起学习新技术,总结学习过程,让你晋级高级高级工程师,学习项目管理,思考职业发展,人生感悟,在充实中成长。有问题或建议,欢迎留言公众号。1、回复“校招”获取推荐码回复“社会招聘”获取推荐回复信息3、每天一题本文为“每日一题”第五题:如何回答“一”每日一题:vue数据绑定的实现原理?第四期“每日一题”与面试官撕代码:如何科学高效地找出重复元素?第三题《每日一题》面试官问你对Promise的理解?可能是你需要能够手动实现每一个特性。第二轨【《【每日一问】ES6为什么要用Symbol?》】(https://mp.weixin.qq.com/s/om...1《一道面试题如何引发心灵深处的拷问?》
