亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Vue 理解之白話 getter/setter詳解

2019-11-19 11:46:15
字體:
來源:轉載
供稿:網友

當你把一個普通的 JavaScript 對象傳給 Vue 實例的 data 選項,Vue 將遍歷此對象所有的屬性,并使用 Object.defineProperty 把這些屬性全部轉為 getter/setter。Object.defineProperty 是 ES5 中一個無法 shim 的特性,這也就是為什么 Vue 不支持 IE8 以及更低版本瀏覽器

 以上摘自 深入響應式原理

那么,把這些屬性全部轉為 getter/setter 具體是怎樣一個過程呢?本文不深入具體,簡單大致了解其過程,旨在整體把握,理解其主要思路

假設代碼如下:

const vm = new Vue({ el: '#app', data: { msg: 'hello world' }})

data 選項可以接收一個對象或者方法,這里以對象為例(其實最后都會轉為對象)

首先,這個對象的所有鍵值對都會被掛載在 vm._data 上(此外 vm._data 對象上還有個 __ob__ key,暫時可以忽視),這樣我們便能用 vm._data.msg 訪問到數據

但是通常我們是用 vm.msg 這樣訪問數據,如何做到的呢?其實就是做了個代理,將 data 鍵值對中的 vm[key] 的訪問都代理到 vm._data[key] 上

proxy(vm, `_data`, key)export function proxy (target: Object, sourceKey: string, key: string) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] } sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val } Object.defineProperty(target, key, sharedPropertyDefinition)}

通常 vm._data (下劃線變量)用作內部程序,對外暴露的 API 是 vm.$data,其實這兩者也是一個東西,也是做了個代理,代碼大概這樣:

const dataDef = {}dataDef.get = function () { return this._data }Object.defineProperty(Vue.prototype, '$data', dataDef)if (process.env.NODE_ENV !== 'production') { dataDef.set = function () { warn(  'Avoid replacing instance root $data. ' +  'Use nested data properties instead.',  this ) }}

簡單理解就是訪問 vm.data.msg 其實就是訪問 vm._data.msg。如果直接在開發環境對 vm.data = xxx這樣的賦值,而不是vm.$data.msg = xxx` 這樣的賦值,后者是沒問題的)

至此,我們理解了為什么能用 vm.msg、vm._data.msg 以及 vm.$data.msg 三種方式獲取/改變數據,最原始的數據是 vm._data.msg,而另外兩者即代理了 _data 的數據,vm.$data.msg 即為 Vue 向外提供的 API,一般情況下開發我們直接用 vm.msg 這樣比較多,也方便,如果要獲取整個 data,程序中需要用 this.$data,而不是 this.data

接下來說 getter/setter

將 demo 稍微添點東西:

const vm = new Vue({ el: '#app', data: { msg: 'hello world' }, computed: { msg2() {  return this.msg + '123' } }})

msg2 是依賴于 msg 的,當 msg 改變的時候,msg2 的值需要自動更新,msg 的改變可以在 vm._data.msg 的 setter 中監聽到,但是怎么知道 msg2 是依賴于 msg 的呢?

直觀地我們可以想到,遍歷所有 computed 對象的鍵值對,然后進行分析,理論上似乎可行,但是我尋思著這可能需要解析 AST 啊,或者正則去匹配,看看是否用到了 this.msg,也可能是 this.$data.msg 啊,還可能是 this._data.msg,而且還要遍歷 data 中的所有 key,這看起來也太麻煩了吧,而且,如果程序中沒有用到 msg2,那不是多此一舉了?

事實上,Vue 初始化的時候會對 vm._data 的每個鍵值對設置 getter/setter,大概代碼如下:

// obj 即為 vm._dataconst keys = Object.keys(obj)for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i])}Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val if (Dep.target) {  dep.depend()  if (childOb) {  childOb.dep.depend()  if (Array.isArray(value)) {   dependArray(value)  }  } } return value }, set: function reactiveSetter (newVal) { const value = getter ? getter.call(obj) : val /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value)) {  return } /* eslint-enable no-self-compare */ if (process.env.NODE_ENV !== 'production' && customSetter) {  customSetter() } // #7981: for accessor properties without setter if (getter && !setter) return if (setter) {  setter.call(obj, newVal) } else {  val = newVal } childOb = !shallow && observe(newVal) dep.notify() }})

Vue 響應式核心就是,setter 的時候會收集依賴,getter 的時候會觸發依賴更新

我們還是以上面的 computed msg2 為例,當我們第一次去取值 msg2 時(注意,必須是取值行為,可以是在 template,也可以是程序中),勢必需要去取值 this.msg,這就會觸發 msg 的 getter,此時我們就可以確定 msg2 依賴于 msg

msg 可以被哪些東西依賴呢?目前看來有三

  1. template 模版中
  2. computed
  3. watch

我們可以打印 vm._watchers 查看,是一個 Watcher 實例數組,直接看實例的 expression 值,其實就是觸發這個表達式的時候,會觸發 msg 的 getter

而這個表達式就對應上述的三種情況,因為 msg 改變的時候,這些表達式需要重新求值,所以這些依賴項都要保存起來,所以源碼中定于了這個 Watcher 類

A watcher parses an expression, collects dependencies, and fires callback when the expression value changes. This is used for both the $watch() api and directives.

 watcher.deps 數組表示該 watcher 的依賴項,值為 Dep 實例,可以理解成和 Watcher 實例的表達式有關的 data 數據。注意,deps 數組可能是空,對于 template 而言,可以是 template 中不依賴于 data,對于 computed 而言,可以是這個 computed 數據還沒被獲取(比如我定義了 msg2,但是程序中沒有用,這時 deps 為空,這表明我如果改變了 msg,但是不需要通知到 msg2,因為 msg2 根本沒用到嘛,但是我在控制臺輸入 vm.msg2,從而觸發了 msg 的 getter,繼而進行了依賴收集,這時 deps 就不為空了,這表明我已經使用了 msg2,下次 msg 更新時需要通知到 msg2 進行改變)

而對于 watch 而言,我試了下任何情況下 deps 都不為空,這需要進一步查看源碼確認

deps 數組元素是 Dep 實例,該實例有個 subs 屬性,是 Watcher 實例數組,表示依賴于這個 Dep 的項目

Watcher 和 Dep 比較難理解,可以暫時這樣理解,Dep 和 data 掛鉤,每一個 Dep 實例就對應 data 的一個鍵值對,Watcher 實例則依賴于 Dep,那么有三個情況會依賴,也就是以上三種(想想是不是這樣,當數據更新的時候,是不是只有這三處需要同時更新,或者同時響應)

總結下:我們會對 data 中所有鍵值對設置 getter/setter,getter 的時候我們會收集依賴(依賴項為上面三項,并不是任何情況下都會收集依賴,比如在鉤子中打印 msg,這時候就沒依賴,所以源碼中這里還有復雜判斷),setter 的時候我們會將收集的依賴項觸發,從而更新數據,理解了這些,就能初步理解 Vue 的響應式原理

以上所述是小編給大家介紹的Vue getter setter詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲男子天堂网| 久久久久久亚洲精品| 久久国产天堂福利天堂| 国产91热爆ts人妖在线| 欧美激情亚洲另类| 国产亚洲欧美视频| 亚洲成色999久久网站| 九九热r在线视频精品| 2021久久精品国产99国产精品| 国产99久久精品一区二区 夜夜躁日日躁| 欧美一级淫片播放口| 欧美激情影音先锋| 亚洲一区美女视频在线观看免费| 久久久免费观看视频| 国产一区二区在线免费| 久久视频在线免费观看| 懂色av中文一区二区三区天美| 亚洲成人在线视频播放| 色婷婷综合久久久久中文字幕1| 热久久这里只有精品| 国产精品视频一区二区三区四| 欧美一区二区三区四区在线| 51ⅴ精品国产91久久久久久| 国产成人精品国内自产拍免费看| 亚洲视频在线观看视频| 91久久国产精品91久久性色| 欧美又大粗又爽又黄大片视频| 精品国产网站地址| 精品一区电影国产| 国产欧美日韩中文字幕在线| 欧洲亚洲免费在线| 91干在线观看| 91香蕉国产在线观看| 亚洲一级一级97网| 亚洲香蕉av在线一区二区三区| 九九热精品视频国产| 欧美精品第一页在线播放| 欧美激情极品视频| 欧美大片大片在线播放| 中文字幕欧美视频在线| 欧美日韩在线视频一区二区| 欧美性猛交xxxx免费看久久久| 欧美日韩精品在线播放| 国产美女搞久久| 欧美电影在线免费观看网站| 久久福利视频导航| 成人中心免费视频| 欧美日韩国产一中文字不卡| 欧美激情国产日韩精品一区18| 亚洲性视频网站| 欧美影院成年免费版| 国产情人节一区| 久久精品国产欧美亚洲人人爽| 亚洲黄色www网站| 日韩在线视频免费观看高清中文| 日韩美女写真福利在线观看| 久久久久久国产| 国产精品流白浆视频| 精品久久久国产| 亚洲欧美日韩天堂一区二区| 91在线观看欧美日韩| 98视频在线噜噜噜国产| 亚洲国产精品字幕| 国产精品视频网| 亚洲美腿欧美激情另类| 国产免费久久av| 精品欧美激情精品一区| 欧美精品一本久久男人的天堂| 北条麻妃一区二区三区中文字幕| 精品人伦一区二区三区蜜桃免费| 国产999精品久久久影片官网| 亚洲香蕉伊综合在人在线视看| 国产精品盗摄久久久| 日韩精品高清视频| 国产精品 欧美在线| 久久久久久久久网站| 欧美激情在线观看视频| 欧美重口另类videos人妖| 欧美日韩精品在线观看| 精品国产一区av| 久久久久中文字幕| 欧洲日本亚洲国产区| 超碰日本道色综合久久综合| 久久久久久国产精品| 国产成+人+综合+亚洲欧美丁香花| 91国产视频在线| 精品高清一区二区三区| 国产成人福利视频| 精品久久久久久电影| 成年无码av片在线| 欧美乱大交做爰xxxⅹ性3| 不卡在线观看电视剧完整版| 久久久国产成人精品| 亚洲影院污污.| 精品一区精品二区| 亚洲精品国产福利| 欧美—级高清免费播放| 亚洲成人在线网| 在线电影欧美日韩一区二区私密| 久久精品国产精品亚洲| 国产网站欧美日韩免费精品在线观看| 亚洲综合最新在线| 亚洲精品一区中文字幕乱码| 欧美夫妻性生活视频| 国产精品爽黄69天堂a| 91九色国产视频| 成年无码av片在线| 国产在线精品播放| 欧美日韩激情网| 亚洲韩国欧洲国产日产av| 国产精品夜色7777狼人| 97精品视频在线观看| 欧美中在线观看| 日韩免费视频在线观看| 久久精品视频在线播放| 欧美孕妇孕交黑巨大网站| 久久免费视频观看| 久久青草精品视频免费观看| 久久69精品久久久久久国产越南| 91香蕉电影院| 欧美尤物巨大精品爽| 一区二区三区视频观看| 日本中文字幕久久看| 亚洲伊人成综合成人网| 亚洲第一精品自拍| 久久久久久久999精品视频| 97视频在线观看视频免费视频| 欧美—级a级欧美特级ar全黄| 国产日产久久高清欧美一区| 日韩在线观看视频免费| 亚洲国产精品久久久久秋霞蜜臀| 亚洲精品永久免费精品| 国产亚洲a∨片在线观看| 国产成人短视频| 国产亚洲精品久久| 国产精品久久久久99| 国产在线视频2019最新视频| 亚洲视频日韩精品| 国产亚洲综合久久| 91亚洲精品久久久| 国产精品久久激情| 91国产高清在线| 一区二区三区视频观看| 久久九九免费视频| yellow中文字幕久久| 亚洲精品98久久久久久中文字幕| 91亚洲国产成人久久精品网站| 欧美日韩精品二区| 中文字幕日韩在线观看| 91在线免费看网站| 国产精品美女www| 欧美日韩午夜视频在线观看| 亚洲欧美日韩视频一区| 性欧美暴力猛交69hd| 少妇av一区二区三区| 国产一区二区欧美日韩| 国产精品影片在线观看| 亚洲3p在线观看| 欧美一二三视频| 中文字幕欧美亚洲| 成人精品aaaa网站| 亚洲国产精品成人av| 日韩中文在线视频| 国产一区二区三区直播精品电影|