摘要:以上引用內(nèi)容來自阮一峰的教程的章節(jié)原文地址請戳這里。最后本文最終實現(xiàn)代碼已經(jīng)放在上,想要直接看效果的同學,可以上去直接,運行。
前言
如果你有讀過Vue的源碼,或者有了解過Vue的響應原理,那么你一定知道Object.defineProperty(),
那么你也應該知道,Vue 2.x里,是通過 遞歸 + 遍歷 data對象來實現(xiàn)對數(shù)據(jù)的監(jiān)控的,
你可能還會知道,我們使用的時候,直接通過數(shù)組的下標給數(shù)組設(shè)置值,不能實時響應,是因為Object.defineProperty()
無法監(jiān)控到數(shù)組下標的變化,而我們平常所用的數(shù)組方法 push, pop, shift, unshift, splice, sort, reverse,
其實不是真正的數(shù)組方法,而是被修改過的,這些都是因為 Object.defineProperty() 提供的能力有限,無法做到完美。
網(wǎng)上看過很多關(guān)于Vue的源碼解讀或者實現(xiàn)一個簡易版的Vue的教程,還都是用 Object.defineProperty (大概是為兼容性考慮吧),
而 Object.defineProperty() 確實存在諸多限制, 據(jù)說Vue的3.x版本會改用Proxy,那么今天我們就先來嘗嘗鮮,用Proxy實現(xiàn)一個簡單版的Vue
Proxy 用于修改某些操作的默認行為,等同于在語言層面做出修改,所以屬于一種“元編程”(meta programming),即對編程語言進行編程。Proxy 可以理解成,在目標對象之前架設(shè)一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
以上引用內(nèi)容來自阮一峰的es6教程的Proxy章節(jié) 原文地址請戳這里。
我們來看看如何用Proxy去定義一個監(jiān)聽數(shù)據(jù)的函數(shù)
定義 observe_observe (data){ var that = this // 把代理器返回的對象存到 this.$data 里面 this.$data = new Proxy(data, { set(target,key,value){ // 利用 Reflect 還原默認的賦值操作 let res = Reflect.set(target,key,value) // 這行就是監(jiān)控代碼了 that.handles[key].map(item => {item.update()}) return res } }) }
當觸發(fā)set的時候,就會執(zhí)行 that.handles[key].map(item => {item.update()}) ,這句代碼的作用就是執(zhí)行 該屬性名下的所有 "監(jiān)視器"
那么,監(jiān)視器怎么來的呢? 請繼續(xù)看以下代碼
定義 compile_compile (root){ const nodes = Array.prototype.slice.call(root.children) let data = this.$data nodes.map(node => { // 如果不是末尾節(jié)點,就遞歸 if(node.children.length > 0) this._complie(node) // 處理 v-bind 指令 if(node.hasAttribute("v-bind")) { let key = node.getAttribute("v-bind") this._pushWatcher(new Watcher(node,"innerHTML",data,key)) } // 處理 v-model 指令 if(node.hasAttribute("v-model")) { let key = node.getAttribute("v-model") this._pushWatcher(new Watcher(node,"value",data,key)) node.addEventListener("input",() => {data[key] = node.value}) } // 處理 v-click 指令 if(node.hasAttribute("v-click")) { let methodName = node.getAttribute("v-click") let mothod = this.$methods[methodName].bind(data) node.addEventListener("click",mothod) } }) }
上面這段代碼,看起來很長,可是實際上,只做了一件很簡單的事情,
就是 "編譯" html 模板,把有 v-bind、v-model、v-click 都給加上對應的 通知 和 監(jiān)控
通知 就是 this._pushWatcher(...) , 相當于是安裝一個監(jiān)聽器,這樣只要 this.$data 有發(fā)生 set 操作的話,就會執(zhí)行
this._pushWatcher 括號里面?zhèn)鞯暮瘮?shù),來通知節(jié)點更新數(shù)據(jù)
監(jiān)控 就是 node.addEventListener(...) 監(jiān)聽相應的事件,然后執(zhí)行對應的 watcher 或者 methods
this._pushWatcher 又做了什么呢?
_pushWatcher (watcher) { if (!this._binding[watcher.key]) this._binding[watcher.key] = [] this._binding[watcher.key].push(watcher) }
這個就更簡單了,如果 this._binding[watcher.key] 為空,就初始化,然后向里面添加一個 監(jiān)聽器
最后,我們再來看看,監(jiān)聽器是怎么實現(xiàn)的
定義 Watcherclass Watcher { constructor (node,attr,data,key) { this.node = node this.attr = attr this.data = data this.key = key } update () { this.node[this.attr] = this.data[this.key] } }
Watcher 是一個類,只有一個方法,就是更新數(shù)據(jù),怎么知道要更新哪個節(jié)點,更新為什么數(shù)據(jù)呢?
在實例化(new)的時候,傳的參數(shù)就是定義這些的
這樣,我們就實現(xiàn)初步的雙向綁定了,整個代碼大概只有50行。其實還可以更少,
但是更少的話,就是繼續(xù)閹割功能了(雖然目前實現(xiàn)的也是嚴重閹割版的),
但是我覺得實現(xiàn)這些,剛好可以不多不少幫我我們理解vue的本質(zhì)。
本文最終實現(xiàn)代碼已經(jīng)放在 github上,想要直接看效果的同學,可以上去直接copy,運行。
如果覺得本文對您有用,請給本文的github加個star,萬分感謝
另外,github上還有其他一些關(guān)于前端的教程和組件,有興趣的童鞋可以看看,你們的支持就是我最大的動力。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95543.html
摘要:結(jié)語因為公司的前后端項目通常都放在同一臺服務器,或者不在同一臺服務器的時候跨域也是靠后端的同志們?nèi)ソ鉀Q的,所以很少在生產(chǎn)環(huán)境中靠前端解決跨域的這項需求。 前言 在使用vue.js開發(fā)前端項目時,再結(jié)合webpack搞起各種依賴、各種插件進行開發(fā),無疑給前端開發(fā)帶來了很多便捷,就在解決跨域這個問題上,相信眾多用vue.js的前端同僚們同我一樣嘗到了甜頭,開發(fā)環(huán)境全靠proxyTable一...
摘要:前言是現(xiàn)階段很流行的前端框架,很多人通過官方文檔的學習,對的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎么更好的管理自己的項目,如何去引入一些框架以及全家桶其他框架的使用,以下將詳細地介紹本人在處理工程文件構(gòu)建的過程對 前言 vue是現(xiàn)階段很流行的前端框架,很多人通過vue官方文檔的學習,對vue的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎...
摘要:前言是現(xiàn)階段很流行的前端框架,很多人通過官方文檔的學習,對的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎么更好的管理自己的項目,如何去引入一些框架以及全家桶其他框架的使用,以下將詳細地介紹本人在處理工程文件構(gòu)建的過程對 前言 vue是現(xiàn)階段很流行的前端框架,很多人通過vue官方文檔的學習,對vue的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎...
摘要:前言是現(xiàn)階段很流行的前端框架,很多人通過官方文檔的學習,對的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎么更好的管理自己的項目,如何去引入一些框架以及全家桶其他框架的使用,以下將詳細地介紹本人在處理工程文件構(gòu)建的過程對 前言 vue是現(xiàn)階段很流行的前端框架,很多人通過vue官方文檔的學習,對vue的使用都有了一定的了解,但再在項目工程化處理的時候,卻發(fā)現(xiàn)不知道改怎...
閱讀 2610·2021-11-23 09:51
閱讀 2523·2021-09-30 09:48
閱讀 1118·2021-09-10 10:51
閱讀 2248·2021-08-12 13:22
閱讀 3605·2021-08-11 10:24
閱讀 2204·2019-08-30 15:55
閱讀 666·2019-08-30 14:05
閱讀 3238·2019-08-30 13:03