亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue.js每天必學(xué)之內(nèi)部響應(yīng)式原理探究

 更新時(shí)間:2021年10月15日 09:48:05   作者:i10630226  
Vue.js每天必學(xué)之內(nèi)部響應(yīng)式原理探究,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

深入響應(yīng)式原理

大部分的基礎(chǔ)內(nèi)容我們已經(jīng)講到了,現(xiàn)在講點(diǎn)底層內(nèi)容。Vue.js 最顯著的一個(gè)功能是響應(yīng)系統(tǒng) —— 模型只是普通對(duì)象,修改它則更新視圖。這讓狀態(tài)管理非常簡(jiǎn)單且直觀,不過理解它的原理也很重要,可以避免一些常見問題。下面我們開始深挖 Vue.js 響應(yīng)系統(tǒng)的底層細(xì)節(jié)。

如何追蹤變化

把一個(gè)普通對(duì)象傳給 Vue 實(shí)例作為它的 data 選項(xiàng),Vue.js 將遍歷它的屬性,用 Object.defineProperty 將它們轉(zhuǎn)為 getter/setter。這是 ES5 特性,不能打補(bǔ)丁實(shí)現(xiàn),這便是為什么 Vue.js 不支持 IE8 及更低版本。

用戶看不到 getter/setters,但是在內(nèi)部它們讓 Vue.js 追蹤依賴,在屬性被訪問和修改時(shí)通知變化。一個(gè)問題是在瀏覽器控制臺(tái)打印數(shù)據(jù)對(duì)象時(shí) getter/setter 的格式化不同,使用 vm.$log() 實(shí)例方法可以得到更友好的輸出。

模板中每個(gè)指令/數(shù)據(jù)綁定都有一個(gè)對(duì)應(yīng)的 watcher 對(duì)象,在計(jì)算過程中它把屬性記錄為依賴。之后當(dāng)依賴的 setter 被調(diào)用時(shí),會(huì)觸發(fā) watcher 重新計(jì)算 ,也就會(huì)導(dǎo)致它的關(guān)聯(lián)指令更新 DOM。

變化檢測(cè)問題

受 ES5 的限制,Vue.js 不能檢測(cè)到對(duì)象屬性的添加或刪除。因?yàn)?Vue.js 在初始化實(shí)例時(shí)將屬性轉(zhuǎn)為 getter/setter,所以屬性必須在 data 對(duì)象上才能讓 Vue.js 轉(zhuǎn)換它,才能讓它是響應(yīng)的。例如:

var data = { a: 1 }
var vm = new Vue({
 data: data
})
// `vm.a` 和 `data.a` 現(xiàn)在是響應(yīng)的

vm.b = 2
// `vm.b` 不是響應(yīng)的

data.b = 2
// `data.b` 不是響應(yīng)的

不過,有辦法在實(shí)例創(chuàng)建之后添加屬性并且讓它是響應(yīng)的。

對(duì)于 Vue 實(shí)例,可以使用 $set(key, value) 實(shí)例方法:

vm.$set('b', 2)
// `vm.b` 和 `data.b` 現(xiàn)在是響應(yīng)的

對(duì)于普通數(shù)據(jù)對(duì)象,可以使用全局方法 Vue.set(object, key, value):

Vue.set(data, 'c', 3)
// `vm.c` 和 `data.c` 現(xiàn)在是響應(yīng)的

有時(shí)你想向已有對(duì)象上添加一些屬性,例如使用 Object.assign() 或 _.extend() 添加屬性。但是,添加到對(duì)象上的新屬性不會(huì)觸發(fā)更新。這時(shí)可以創(chuàng)建一個(gè)新的對(duì)象,包含原對(duì)象的屬性和新的屬性:

// 不使用 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

也有一些數(shù)組相關(guān)的問題,之前已經(jīng)在列表渲染中講過。

初始化數(shù)據(jù)

盡管 Vue.js 提供了 API 動(dòng)態(tài)地添加響應(yīng)屬性,還是推薦在 data 對(duì)象上聲明所有的響應(yīng)屬性。

不這么做:

var vm = new Vue({
 template: '<div>{{msg}}</div>'
})
// 然后添加 `msg`
vm.$set('msg', 'Hello!')

這么做:

var vm = new Vue({
 data: {
 // 以一個(gè)空值聲明 `msg`
 msg: ''
 },
 template: '<div>{{msg}}</div>'
})
// 然后設(shè)置 `msg`
vm.msg = 'Hello!'

這么做有兩個(gè)原因:
 1.data 對(duì)象就像組件狀態(tài)的模式(schema)。在它上面聲明所有的屬性讓組件代碼更易于理解。

 2.添加一個(gè)頂級(jí)響應(yīng)屬性會(huì)強(qiáng)制所有的 watcher 重新計(jì)算,因?yàn)樗安淮嬖?,沒有 watcher 追蹤它。這么做性能通常是可以接受的(特別是對(duì)比 Angular 的臟檢查),但是可以在初始化時(shí)避免。

異步更新隊(duì)列

Vue.js 默認(rèn)異步更新 DOM。每當(dāng)觀察到數(shù)據(jù)變化時(shí),Vue 就開始一個(gè)隊(duì)列,將同一事件循環(huán)內(nèi)所有的數(shù)據(jù)變化緩存起來(lái)。如果一個(gè) watcher 被多次觸發(fā),只會(huì)推入一次到隊(duì)列中。等到下一次事件循環(huán),Vue 將清空隊(duì)列,只進(jìn)行必要的 DOM 更新。在內(nèi)部異步隊(duì)列優(yōu)先使用 MutationObserver,如果不支持則使用 setTimeout(fn, 0)。

例如,設(shè)置了 vm.someData = 'new value',DOM 不會(huì)立即更新,而是在下一次事件循環(huán)清空隊(duì)列時(shí)更新。我們基本不用關(guān)心這個(gè)過程,但是如果想在 DOM 狀態(tài)更新后做點(diǎn)什么,這會(huì)有幫助。盡管 Vue.js 鼓勵(lì)開發(fā)者沿著數(shù)據(jù)驅(qū)動(dòng)的思路,避免直接修改 DOM,但是有時(shí)確實(shí)要這么做。為了在數(shù)據(jù)變化之后等待 Vue.js 完成更新 DOM,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) ?;卣{(diào)在 DOM 更新完成后調(diào)用。例如:

<div id="example">{{msg}}</div>

var vm = new Vue({
 el: '#example',
 data: {
 msg: '123'
 }
})
vm.msg = 'new message' // 修改數(shù)據(jù)
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
 vm.$el.textContent === 'new message' // true
})

vm.$nextTick() 這個(gè)實(shí)例方法比較方便,因?yàn)樗恍枰?Vue,它的回調(diào)的 this 自動(dòng)綁定到當(dāng)前 Vue 實(shí)例:

Vue.component('example', {
 template: '<span>{{msg}}</span>',
 data: function () {
 return {
 msg: 'not updated'
 }
 },
 methods: {
 updateMessage: function () {
 this.msg = 'updated'
 console.log(this.$el.textContent) // => 'not updated'
 this.$nextTick(function () {
 console.log(this.$el.textContent) // => 'updated'
 })
 }
 }
})

計(jì)算屬性的奧秘

你應(yīng)該注意到 Vue.js 的計(jì)算屬性不是簡(jiǎn)單的 getter。計(jì)算屬性持續(xù)追蹤它的響應(yīng)依賴。在計(jì)算一個(gè)計(jì)算屬性時(shí),Vue.js 更新它的依賴列表并緩存結(jié)果,只有當(dāng)其中一個(gè)依賴發(fā)生了變化,緩存的結(jié)果才無(wú)效。因此,只要依賴不發(fā)生變化,訪問計(jì)算屬性會(huì)直接返回緩存的結(jié)果,而不是調(diào)用 getter。

為什么要緩存呢?假設(shè)我們有一個(gè)高耗計(jì)算屬性 A,它要遍歷一個(gè)巨型數(shù)組并做大量的計(jì)算。然后,可能有其它的計(jì)算屬性依賴 A。如果沒有緩存,我們將調(diào)用 A 的 getter 許多次,超過必要次數(shù)。

由于計(jì)算屬性被緩存了,在訪問它時(shí) getter 不總是被調(diào)用??紤]下例:

var vm = new Vue({
 data: {
 msg: 'hi'
 },
 computed: {
 example: function () {
 return Date.now() + this.msg
 }
 }
})

計(jì)算屬性 example 只有一個(gè)依賴:vm.msg。Date.now() 不是 響應(yīng)依賴,因?yàn)樗?Vue 的數(shù)據(jù)觀察系統(tǒng)無(wú)關(guān)。因而,在訪問 vm.example 時(shí)將發(fā)現(xiàn)時(shí)間戳不變,除非 vm.msg 變了。

有時(shí)希望 getter 不改變?cè)械男袨?,每次訪問 vm.example 時(shí)都調(diào)用 getter。這時(shí)可以為指定的計(jì)算屬性關(guān)閉緩存:

computed: {
 example: {
 cache: false,
 get: function () {
 return Date.now() + this.msg
 }
 }
}

現(xiàn)在每次訪問 vm.example 時(shí),時(shí)間戳都是新的。但是,只是在 JavaScript 中訪問是這樣的;數(shù)據(jù)綁定仍是依賴驅(qū)動(dòng)的。如果在模塊中這樣綁定計(jì)算屬性 {{example}},只有響應(yīng)依賴發(fā)生變化時(shí)才更新 DOM。

本文已被整理到了《Vue.js前端組件學(xué)習(xí)教程》,歡迎大家學(xué)習(xí)閱讀。

關(guān)于vue.js組件的教程,請(qǐng)大家點(diǎn)擊專題vue.js組件學(xué)習(xí)教程進(jìn)行學(xué)習(xí)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論