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

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://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)
91一区二区三区在线| 亚洲欧美极品一区色婷婷| 亚洲成a人片777777久久| 国产精品一区二区久久毛片| 日韩欧美国产麻豆一区精品| 九九久久亚洲av成人乱片| 精品亚洲综合一区二区| 欧美日韩激情在线一区| 精品亚洲欧美日韩国产| 国一区二区三区四区av| 国产模特一区二区三区| 日韩人妖视频在线观看| 亚洲av二区三区成人| 一区二区三区日韩欧美在线| 亚洲欧美中文日韩二区一区| 日本免费精品人成视频| 日韩欧美一级性生活片| 女同蝴蝶在线看完整版| 日本岛国大片一区二区在线观看| 91超碰在线观看中文| 日本国产一区二区三区在线观看| 午夜福利欧美日本视频| 亚洲毛片免费视频久久| 乡村丰满的大屁股熟妇| 蜜臀一二区免费在线视频| 精品日韩欧美在线观看91| 午夜射精视频在线观看| 国产麻豆成人传媒免费观看| 天天操天天干蜜桃av| 日韩夫妻精品熟妇人妻一区| 欧美成人午夜精品一区二区| 一区二区三区欧美日韩在线| 精品少妇一区二区三区| 免费看欧美粗又大爽老| 日韩爱爱特级视频中文字幕| 午夜福利主播一区二区| 日韩av裸体在线播放| 人人人妻人人澡人人爽e| 国产特级黄色片免费看| 男人天堂手机视频在线| av在线成人国产精品欧美|