分享前啰嗦
我之前介绍过vue1.0如何实现和。本想继续写下去,可是vue2.0横空出世. .所以直接看vue2.0吧。这篇文章在公司分享过,终于写出来了。我们采用用最精简的代码,还原vue2.0响应式架构实现。
以前写的那篇vue源码分析之如何实现观察者和观察者可以作为本次分享的参考。
不过不看也没关系,但是最好了解下Object.defineProperty
<强>本文分享什么强>
理解vue2.0的响应式架构,就是下面这张图
const演示=new Vue ({ 数据:{ 文本:“之前”, },//对应的模板为& lt; div> & lt; span>{{文本}}& lt;/span> & lt;/div> 呈现(h) { 返回h (" div " {}, ( h(“跨越”,{},[this.__toString__ (this.text))) ]) } }) setTimeout(函数(){ 演示。文本="后" },3000) >之前
对应的虚拟dom会从
变为
好,开始吧! ! !
<强>第一步,强>讲数据下面所有属性变为可见
来来来先看代码吧
类Vue { 构造函数(选项){ 这一点。美元选项=选项 这一点。_data=https://www.yisu.com/zixun/options.data 观察者(选项。数据、this._update) this._update () } _update () { options.render美元。() } } 函数观察者(价值,cb) { 种(值).forEach((关键)=> defineReactive(价值、关键值(例子),cb)) } 函数defineReactive (obj,钥匙,val, cb) { Object.defineProperty (obj,钥匙,{ 可列举的:真的, 可配置:没错, 得到:()=> {}, 设置:newVal=> { cb () } }) } Vue ({var=new演示 艾尔:#演示, 数据:{ 文本:123, }, 呈现(){ console.log(“我要渲染了”) } }) setTimeout(函数(){ demo._data。文本=444 },3000) >之前为了好演示我们只考虑最简单的情况,如果看了vue源码分析之如何实现观察者和观察者可能就会很好理解,不过没关系,我们三言两语再说说,这段代码要实现的功能就是将
Vue ({var=new演示 艾尔:#演示, 数据:{ 文本:123, }, 呈现(){ console.log(“我要渲染了”) } }) >之前中数据里面所有的属性置于观察者,然后数据里面的属性,比如文本以改变,就引起_update()函数调用进而重新渲染,是怎样做到的呢,我们知道其实就是赋值的时候就要改变对吧,当我给数据下面赋的文本值的时候集函数就会触发,这个时候调用_update就好了,但是
setTimeout(函数(){ demo._data。文本=444 },3000) >之前demo._data.text没有demo.text用着爽,没关系,我们加一个代理
_proxy(键){ const自我=这 Object.defineProperty(自我,关键,{ 可配置:没错, 可列举的:真的, 得到:proxyGetter函数(){ 返回self._data(例子) }, 设置:函数proxySetter (val) { 自我。_data(例子)=瓦尔 } }) } >之前然后在Vue的构造函数加上下面这句
第一步先说到这里,我们会发现一个问题,数据中任何一个属性的值改变,都会引起
_update的触发进而重新渲染,属性这显然不够精准啊<强>第二步,强>详细阐述第一步为什么不够精准
比如考虑下面代码
新Vue ({ 模板: & lt; div> & lt; section> & lt; span>名称:& lt;/span>{{名称}} & lt;/section> & lt; section> & lt; span>年龄:& lt;/span>{{年龄}} & lt;/section> & lt; div>” 数据:{ 名称:“js”, 年龄:24岁 身高:180 } }) setTimeout(函数(){ 演示。身高=181 },3000) >之前里面只用到了上的两个属性和,但是当我改变的时候,用第一步的代码,会不会触发重新渲染吗?会,但其实不需要触发重新渲染,这就是问题所在! !
100行代码理解和分析vue2.0响应式架构