国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

使用proxy實現一個更優雅的vue【推薦】

2019-11-19 13:38:21
字體:
來源:轉載
供稿:網友

如果你有讀過Vue的源碼,或者有了解過Vue的響應原理,那么你一定知道Object.defineProperty(), 那么你也應該知道,Vue 2.x里,是通過 遞歸 + 遍歷 data 對象來實現對數據的監控的, 你可能還會知道,我們使用的時候,直接通過數組的下標給數組設置值,不能實時響應,是因為Object.defineProperty() 無法監控到數組下標的變化,而我們平常所用的數組方法 push , pop , shift , unshift , splice , sort , reverse , 其實不是真正的數組方法,而是被修改過的,這些都是因為 Object.defineProperty() 提供的能力有限,無法做到完美。

網上看過很多關于Vue的源碼解讀或者實現一個簡易版的Vue的教程,還都是用 Object.defineProperty (大概是為兼容性考慮吧), 而 Object.defineProperty() 確實存在諸多限制, 據說Vue的3.x版本會改用Proxy,那么今天我們就先來嘗嘗鮮,用Proxy實現一個簡單版的Vue

proxy 介紹

Proxy 用于修改某些操作的默認行為,等同于在語言層面做出修改,所以屬于一種“元編程”(meta programming),即對編程語言進行編程。

Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。

以上引用內容來自阮一峰的es6教程的Proxy章節 原文地址請戳這里。

我們來看看如何用Proxy去定義一個監聽數據的函數

定義 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) // 這行就是監控代碼了 that.handles[key].map(item => {item.update()}) return res } })}

當觸發set的時候,就會執行 that.handles[key].map(item => {item.update()}) ,這句代碼的作用就是執行 該屬性名下的所有 "監視器"

那么,監視器怎么來的呢? 請繼續看以下代碼

定義 compile

_compile (root){ const nodes = Array.prototype.slice.call(root.children) let data = this.$data nodes.map(node => {  // 如果不是末尾節點,就遞歸  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 都給加上對應的 通知 和 監控

1.通知就是 this._pushWatcher(...) , 相當于是安裝一個監聽器,這樣只要 this.$data 有發生 set 操作的話,就會執行 this._pushWatcher 括號里面傳的函數,來通知節點更新數據

2.監控就是 node.addEventListener(...) 監聽相應的事件,然后執行對應的 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] 為空,就初始化,然后向里面添加一個 監聽器

最后,我們再來看看,監聽器是怎么實現的

定義 Watcher

class 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 是一個類,只有一個方法,就是更新數據,怎么知道要更新哪個節點,更新為什么數據呢? 在實例化(new)的時候,傳的參數就是定義這些的

這樣,我們就實現初步的雙向綁定了,整個代碼大概只有50行。其實還可以更少, 但是更少的話,就是繼續閹割功能了(雖然目前實現的也是嚴重閹割版的), 但是我覺得實現這些,剛好可以不多不少幫我我們理解vue的本質。

最后

本文最終實現代碼已經放在 github 上,想要直接看效果的同學,可以上去直接copy,運行。

如果覺得本文對您有用,請給本文的github 加個star,萬分感謝

另外, github 上還有其他一些關于前端的教程和組件,有興趣的童鞋可以看看,你們的支持就是我最大的動力。

總結

以上所述是小編給大家介紹的使用proxy實現一個更優雅的vue,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 喀什市| 长丰县| 芮城县| 华池县| 云安县| 深水埗区| 桐城市| 鸡东县| 建宁县| 莆田市| 阜新市| 宜春市| 武川县| 深泽县| 威远县| 共和县| 贡嘎县| 曲靖市| 安丘市| 尚志市| 许昌市| 永靖县| 根河市| 二连浩特市| 绥滨县| 泰兴市| 金乡县| 西贡区| 阳城县| 宁晋县| 桃园县| 阿合奇县| 吴桥县| 昌平区| 和平区| 武城县| 祁东县| 改则县| 东乌| 东乌珠穆沁旗| 高陵县|