欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Vue理解之白話getter/setter詳解

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

專注于為中小企業(yè)提供成都網(wǎng)站制作、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)龍?zhí)睹赓M(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

 以上摘自 深入響應(yīng)式原理

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

假設(shè)代碼如下:

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

data 選項(xiàng)可以接收一個(gè)對(duì)象或者方法,這里以對(duì)象為例(其實(shí)最后都會(huì)轉(zhuǎn)為對(duì)象)

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

但是通常我們是用 vm.msg 這樣訪問數(shù)據(jù),如何做到的呢?其實(shí)就是做了個(gè)代理,將 data 鍵值對(duì)中的 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 (下劃線變量)用作內(nèi)部程序,對(duì)外暴露的 API 是 vm.$data,其實(shí)這兩者也是一個(gè)東西,也是做了個(gè)代理,代碼大概這樣:

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
 )
 }
}

簡(jiǎn)單理解就是訪問 vm.data.msg 其實(shí)就是訪問 vm._data.msg。如果直接在開發(fā)環(huán)境對(duì) vm.data = xxx這樣的賦值,而不是vm.$data.msg = xxx` 這樣的賦值,后者是沒問題的)

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

接下來說 getter/setter

將 demo 稍微添點(diǎn)東西:

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

msg2 是依賴于 msg 的,當(dāng) msg 改變的時(shí)候,msg2 的值需要自動(dòng)更新,msg 的改變可以在 vm._data.msg 的 setter 中監(jiān)聽到,但是怎么知道 msg2 是依賴于 msg 的呢?

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

事實(shí)上,Vue 初始化的時(shí)候會(huì)對(duì) vm._data 的每個(gè)鍵值對(duì)設(shè)置 getter/setter,大概代碼如下:

// obj 即為 vm._data
const 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 響應(yīng)式核心就是,setter 的時(shí)候會(huì)收集依賴,getter 的時(shí)候會(huì)觸發(fā)依賴更新

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

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

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

我們可以打印 vm._watchers 查看,是一個(gè) Watcher 實(shí)例數(shù)組,直接看實(shí)例的 expression 值,其實(shí)就是觸發(fā)這個(gè)表達(dá)式的時(shí)候,會(huì)觸發(fā) msg 的 getter

而這個(gè)表達(dá)式就對(duì)應(yīng)上述的三種情況,因?yàn)?msg 改變的時(shí)候,這些表達(dá)式需要重新求值,所以這些依賴項(xiàng)都要保存起來,所以源碼中定于了這個(gè) 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 數(shù)組表示該 watcher 的依賴項(xiàng),值為 Dep 實(shí)例,可以理解成和 Watcher 實(shí)例的表達(dá)式有關(guān)的 data 數(shù)據(jù)。注意,deps 數(shù)組可能是空,對(duì)于 template 而言,可以是 template 中不依賴于 data,對(duì)于 computed 而言,可以是這個(gè) computed 數(shù)據(jù)還沒被獲取(比如我定義了 msg2,但是程序中沒有用,這時(shí) deps 為空,這表明我如果改變了 msg,但是不需要通知到 msg2,因?yàn)?msg2 根本沒用到嘛,但是我在控制臺(tái)輸入 vm.msg2,從而觸發(fā)了 msg 的 getter,繼而進(jìn)行了依賴收集,這時(shí) deps 就不為空了,這表明我已經(jīng)使用了 msg2,下次 msg 更新時(shí)需要通知到 msg2 進(jìn)行改變)

而對(duì)于 watch 而言,我試了下任何情況下 deps 都不為空,這需要進(jìn)一步查看源碼確認(rèn)

deps 數(shù)組元素是 Dep 實(shí)例,該實(shí)例有個(gè) subs 屬性,是 Watcher 實(shí)例數(shù)組,表示依賴于這個(gè) Dep 的項(xiàng)目

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

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

以上所述是小編給大家介紹的Vue getter setter詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!

文章題目:Vue理解之白話getter/setter詳解
本文URL:http://www.aaarwkj.com/article36/igoipg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、關(guān)鍵詞優(yōu)化、響應(yīng)式網(wǎng)站、企業(yè)網(wǎng)站制作、網(wǎng)站制作、營(yíng)銷型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)
欧亚日韩精品一区二区在线| 在线视频天堂亚洲天堂| 免费精品黑人一区二区三区| 亚洲一区日本一区二区| 午夜亚洲欧美日韩在线| 国产自拍成人精品视频| 国产亚洲日本一区二区三区| 精品人妻一区二区在线99| 女性裸体无遮挡啪啪网站| 最新人妻少妇精品中文字幕视频| 天天干夜夜操操操操| 99久久精品费精品国产风间由美| 熟女精品国产一区二区三区| 日本一区二区三区日韩欧美 | 日韩一区不卡在线观看| 闫国产一区二区三区色噜噜| 精品少妇人妻av不卡久久| 国产区二区三区在线视频| 最新人妻少妇精品中文字幕视频| 久久国产精品久久国产精品| 久章草在线免费视频播放| 人妻精品久久一区二区三区| 岛国av有码高清在线观看| 黄色大片黄色大片黄色大片| 国产精品极品网站91青青| 久久好大好爽要死了欧美| 国产系列在线播放一区二区三区| 日本不卡的三区四区五区| 久久se精品一区精品二区国产| 久久中文字幕人妻熟av| 国产精品专区日产一区| 日本一区中文字幕怎么用| 岛国大片日韩在线观看| 国产一区二区三区高潮爽| 黄色国产欧美国产亚洲| 91精品婷婷国产综合| 97精品免费在线观看| 伊人激情久久综合中文字幕| 国产成人自拍视频网站| 欧美伊香蕉久久综合网99| 日韩成人在线视频观看|