写在前面是因为我对Vue.js很感兴趣,平时工作的技术栈也是Vue.js。在过去的几个月里,我花了一些时间研究和研究Vue.js的源代码,并做了总结和输出。文章原文地址:https://github.com/answershuto/learnVue。在学习过程中,我在Vuehttps://github.com/answershuto/learnVue/tree/master/vue-src添加了中文注释,希望对其他想学习Vue源码的朋友有所帮助。理解上可能会有偏差。欢迎提交issue,共同学习进步。关于Vue.jsVue.js是一个MVVM框架,使用起来快速简单,通过响应式在修改数据时更新视图。Vue.js的响应式原理依赖于Object.defineProperty,友达在Vue.js文档中提到过,这也是Vue.js不支持E8及以下浏览器的原因。Vue通过设置对象属性的setter/getter方法来监听数据变化,通过getter收集依赖,每个setter方法都是一个观察者,当数据变化时通知订阅者更新视图。让数据数据可观察(observable),那么Vue是如何让所有数据下的所有属性都可观察(observable)的呢?functionobserver(value){Object.keys(value).forEach((key)=>defineReactive(value,key,value[key],cb))}functiondefineReactive(obj,key,val,cb){Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:()=>{/*....依赖集合等....*/},set:newVal=>{cb();/*回调订阅者接收消息*/}})}classVue{constructor(options){this._data=options.data;observer(this._data,options.render)}}letapp=newVue({el:'#app',data:{text:'text',text2:'text2'},render(){console.log("render");}})为了便于理解,先考虑最简单的情况,忽略数组等情况,代码如上所示。在initData中,将调用observe函数将Vue数据设置为可观察的。当_data数据发生变化时,会触发set,回调订阅者(renderhere)。那么问题来了,需要对app._date.text进行操作来触发set。为了偷懒,我们需要一个方便的方式来触发设置重绘视图,直接设置app.text即可。然后你需要使用代理。Proxy我们可以在Vue的构造函数中为数据实现一个proxy代理。通过这种方式,我们将数据上的属性代理到vm实例。_proxy(options.data);/*在构造函数中*//*proxy*/function_proxy(data){constthat=this;Object.keys(data).forEach(key=>{Object.defineProperty(that,key,{configurable:true,enumerable:true,get:functionproxyGetter(){returnthat._data[key];},set:functionproxySetter(val){that._data[key]=val;}})});}我们可以使用app.text替换app._data.text。
