真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么理解vue2.0響應(yīng)式架構(gòu)

本篇內(nèi)容主要講解“怎么理解vue2.0響應(yīng)式架構(gòu)”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“怎么理解vue2.0響應(yīng)式架構(gòu)”吧!

創(chuàng)新互聯(lián)公司:從2013年創(chuàng)立為各行業(yè)開(kāi)拓出企業(yè)自己的“網(wǎng)站建設(shè)”服務(wù),為上1000家公司企業(yè)提供了專(zhuān)業(yè)的網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)和網(wǎng)站推廣服務(wù), 按需搭建網(wǎng)站由設(shè)計(jì)師親自精心設(shè)計(jì),設(shè)計(jì)的效果完全按照客戶(hù)的要求,并適當(dāng)?shù)奶岢龊侠淼慕ㄗh,擁有的視覺(jué)效果,策劃師分析客戶(hù)的同行競(jìng)爭(zhēng)對(duì)手,根據(jù)客戶(hù)的實(shí)際情況給出合理的網(wǎng)站構(gòu)架,制作客戶(hù)同行業(yè)具有領(lǐng)先地位的。

講data 下面所有屬性變?yōu)閛bservable

來(lái)來(lái)來(lái)先看代碼吧

class Vue {       constructor(options) {         this.$options = options         this._data = options.data         observer(options.data, this._update)         this._update()       }       _update(){         this.$options.render()       }     }       function observer(value, cb){       Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))     }      function defineReactive(obj, key, val, cb) {       Object.defineProperty(obj, key, {         enumerable: true,         configurable: true,         get: ()=>{},         set:newVal=> {           cb()         }       })     }      var demo = new Vue({       el: '#demo',       data: {         text: 123,       },       render(){         console.log("我要render了")       }     })       setTimeout(function(){        demo._data.text = 444      }, 3000)

為了好演示我們只考慮最簡(jiǎn)單的情況,如果看了vue 源碼分析之如何實(shí)現(xiàn) observer 和  watcher可能就會(huì)很好理解,不過(guò)沒(méi)關(guān)系,我們?nèi)詢(xún)烧Z(yǔ)再說(shuō)說(shuō),這段代碼要實(shí)現(xiàn)的功能就是將

var demo = new Vue({      el: '#demo',      data: {        text: 123,      },      render(){        console.log("我要render了")      }    })

中data 里面所有的屬性置于 observer,然后data里面的屬性,比如 text  以改變,就引起_update()函數(shù)調(diào)用進(jìn)而重新渲染,是怎樣做到的呢,我們知道其實(shí)就是賦值的時(shí)候就要改變對(duì)吧,當(dāng)我給data下面的text 賦值的時(shí)候 set  函數(shù)就會(huì)觸發(fā),這個(gè)時(shí)候 調(diào)用_update 就ok了,但是

setTimeout(function(){       demo._data.text = 444     }, 3000)

demo._data.text沒(méi)有demo.text用著爽,沒(méi)關(guān)系,我們加一個(gè)代理

_proxy(key) {       const self = this       Object.defineProperty(self, key, {         configurable: true,         enumerable: true,         get: function proxyGetter () {           return self._data[key]         },         set: function proxySetter (val) {           self._data[key] = val         }       })     }

然后在Vue的constructor加上下面這句

Object.keys(options.data).forEach(key => this._proxy(key))

***步先說(shuō)到這里,我們會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,data中任何一個(gè)屬性的值改變,都會(huì)引起

_update的觸發(fā)進(jìn)而重新渲染,屬性這顯然不夠精準(zhǔn)啊

第二步,詳細(xì)闡述***步為什么不夠精準(zhǔn)

比如考慮下面代碼

new Vue({      template: `        
          
            name: {{name}}          
          
            age: {{age}}          
        
`,      data: {        name: 'js',        age: 24,        height: 180      }    })     setTimeout(function(){      demo.height = 181    }, 3000)

template里面只用到了data上的兩個(gè)屬性name和age,但是當(dāng)我改變height的時(shí)候,用***步的代碼,會(huì)不會(huì)觸發(fā)重新渲染?會(huì)!,但其實(shí)不需要觸發(fā)重新渲染,這就是問(wèn)題所在!!

第三步,上述問(wèn)題怎么解決

簡(jiǎn)單說(shuō)說(shuō)虛擬 DOM

首先,template***都是編譯成render函數(shù)的(具體怎么做,就不展開(kāi)說(shuō)了,以后我會(huì)說(shuō)的),然后render  函數(shù)執(zhí)行完就會(huì)得到一個(gè)虛擬DOM,為了好理解我們寫(xiě)寫(xiě)最簡(jiǎn)單的虛擬DOM

function VNode(tag, data, children, text) {       return {         tag: tag,         data: data,         children: children,         text: text       }     }      class Vue {       constructor(options) {         this.$options = options         const vdom = this._update()         console.log(vdom)       }       _update() {         return this._render.call(this)       }       _render() {         const vnode = this.$options.render.call(this)         return vnode       }       __h__(tag, attr, children) {         return VNode(tag, attr, children.map((child)=>{           if(typeof child === 'string'){             return VNode(undefined, undefined, undefined, child)           }else{             return child           }         }))       }       __toString__(val) {         return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);       }     }       var demo = new Vue({       el: '#demo',       data: {         text: "before",       },       render(){         return this.__h__('div', {}, [           this.__h__('span', {}, [this.__toString__(this.text)])         ])       }     })

我們運(yùn)行一下,他會(huì)輸出

{       tag: 'div',       data: {},       children:[         {           tag: 'span',           data: {},           children: [             {               children: undefined,               data: undefined,               tag: undefined,               text: '' // 正常情況為 字符串 before,因?yàn)槲覀優(yōu)榱搜菔揪筒粚?xiě)代理的代碼,所以這里為空             }           ]         }       ]     }

這就是 虛擬最簡(jiǎn)單虛擬DOM,tag是html 標(biāo)簽名,data 是包含諸如 class 和 style  這些標(biāo)簽上的屬性,childen就是子節(jié)點(diǎn),關(guān)于虛擬DOM就不展開(kāi)說(shuō)了。

回到開(kāi)始的問(wèn)題,也就是說(shuō),我得知道,render 函數(shù)里面依賴(lài)了vue實(shí)例里面哪些變量(只考慮render 就可以,因?yàn)閠emplate  也會(huì)是幫你編譯成render)。敘述有點(diǎn)拗口,還是看代碼吧

var demo = new Vue({       el: '#demo',       data: {         text: "before",         name: "123",         age: 23       },       render(){         return this.__h__('div', {}, [           this.__h__('span', {}, [this.__toString__(this.text)])         ])       }     })

就像這段代碼,render 函數(shù)里其實(shí)只依賴(lài)text,并沒(méi)有依賴(lài) name和 age,所以,我們只要text改變的時(shí)候

我們自動(dòng)觸發(fā) render 函數(shù)  讓它生成一個(gè)虛擬DOM就ok了(剩下的就是這個(gè)虛擬DOM和上個(gè)虛擬DOM做比對(duì),然后操作真實(shí)DOM,只能以后再說(shuō)了),那么我們正式考慮一下怎么做

第三步,'touch' 拿到依賴(lài)

回到最上面那張圖,我們知道data上的屬性設(shè)置defineReactive后,修改data 上的值會(huì)觸發(fā) set。

那么我們?nèi)ata上值是會(huì)觸發(fā) get了。

對(duì),我們可以在上面做做手腳,我們先執(zhí)行一下render,我們看看data上哪些屬性觸發(fā)了get,我們豈不是就可以知道 render 會(huì)依賴(lài)data  上哪些變量了。

然后我么把這些變量做些手腳,每次這些變量變的時(shí)候,我們就觸發(fā)render。

上面這些步驟簡(jiǎn)單用四個(gè)子概括就是 計(jì)算依賴(lài)。

(其實(shí)不僅是render,任何一個(gè)變量的改別,是因?yàn)閯e的變量改變引起,都可以用上述方法,也就是computed 和 watch  的原理,也是mobx的核心)

***步,

我們寫(xiě)一個(gè)依賴(lài)收集的類(lèi),每一個(gè)data 上的對(duì)象都有可能被render函數(shù)依賴(lài),所以每個(gè)屬性在defineReactive

時(shí)候就初始化它,簡(jiǎn)單來(lái)說(shuō)就是這個(gè)樣子的

class Dep {       constructor() {         this.subs = []       }       add(cb) {         this.subs.push(cb)       }       notify() {         console.log(this.subs);         this.subs.forEach((cb) => cb())       }     }     function defineReactive(obj, key, val, cb) {       const dep = new Dep()       Object.defineProperty(obj, key, {         // 省略       })     }

然后,當(dāng)執(zhí)行render 函數(shù)去'touch'依賴(lài)的時(shí)候,依賴(lài)到的變量get就會(huì)被執(zhí)行,然后我們就可以把這個(gè) render 函數(shù)加到 subs  里面去了。

當(dāng)我們,set 的時(shí)候 我們就執(zhí)行 notify 將所有的subs數(shù)組里的函數(shù)執(zhí)行,其中就包含render 的執(zhí)行。

至此就完成了整個(gè)圖,好我們將所有的代碼展示出來(lái)

function VNode(tag, data, children, text) {      return {        tag: tag,        data: data,        children: children,        text: text      }    }     class Vue {      constructor(options) {        this.$options = options        this._data = options.data        Object.keys(options.data).forEach(key => this._proxy(key))        observer(options.data)        const vdom = watch(this, this._render.bind(this), this._update.bind(this))        console.log(vdom)      }      _proxy(key) {        const self = this        Object.defineProperty(self, key, {          configurable: true,          enumerable: true,          get: function proxyGetter () {            return self._data[key]          },          set: function proxySetter (val) {            self._data.text = val          }        })      }      _update() {        console.log("我需要更新");        const vdom = this._render.call(this)        console.log(vdom);      }      _render() {        return this.$options.render.call(this)      }      __h__(tag, attr, children) {        return VNode(tag, attr, children.map((child)=>{          if(typeof child === 'string'){            return VNode(undefined, undefined, undefined, child)          }else{            return child          }        }))      }      __toString__(val) {        return val == null ? '' : typeof val === 'object' ? JSON.stringify(val, null, 2) : String(val);      }    }     function observer(value, cb){      Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))    }     function defineReactive(obj, key, val, cb) {      const dep = new Dep()      Object.defineProperty(obj, key, {        enumerable: true,        configurable: true,        get: ()=>{          if(Dep.target){            dep.add(Dep.target)          }          return val        },        set: newVal => {          if(newVal === val)            return          val = newVal          dep.notify()        }      })    }    function watch(vm, exp, cb){      Dep.target = cb      return exp()    }     class Dep {      constructor() {        this.subs = []      }      add(cb) {        this.subs.push(cb)      }      notify() {        this.subs.forEach((cb) => cb())      }    }    Dep.target = null      var demo = new Vue({      el: '#demo',      data: {        text: "before",      },      render(){        return this.__h__('div', {}, [          this.__h__('span', {}, [this.__toString__(this.text)])        ])      }    })       setTimeout(function(){       demo.text = "after"     }, 3000)

我們看一下運(yùn)行結(jié)果

怎么理解vue2.0響應(yīng)式架構(gòu)

好我們解釋一下 Dep.target 因?yàn)槲覀兊脜^(qū)分是,普通的get,還是在查找依賴(lài)的時(shí)候的get,

所有我們?cè)诓檎乙蕾?lài)時(shí)候,我們將

function watch(vm, exp, cb){       Dep.target = cb       return exp()     }

Dep.target 賦值,相當(dāng)于 flag 一下,然后 get 的時(shí)候

get: () => {           if (Dep.target) {             dep.add(Dep.target)           }           return val         },

到此,相信大家對(duì)“怎么理解vue2.0響應(yīng)式架構(gòu)”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!


新聞標(biāo)題:怎么理解vue2.0響應(yīng)式架構(gòu)
網(wǎng)頁(yè)URL:http://weahome.cn/article/psphgi.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部