做(zuò)自(zì)由與創造的先行(xíng)者

響應式基礎

Vue.js中文手冊

聲明(míng)響應式狀态 ​

選用選項式 API 時(shí),會用 data 選項來聲明(míng)組件的響應式狀态。此選項的值應為(wèi)返回一(yī)個對象的函數(shù)。Vue 将在創建新組件實例的時(shí)候調用此函數(shù),并将函數(shù)返回的對象用響應式系統進行(xíng)包裝。此對象的所有頂層屬性都(dōu)會被代理到組件實例 (即方法和(hé)生命周期鈎子中的 this) 上(shàng)。

js

export default {

data() {

return {

count: 1

}

},

// `mounted` 是生命周期鈎子,之後我們會講到

mounted() {

// `this` 指向當前組件實例

console.log(this.count) // => 1

// 數(shù)據屬性也可(kě)以被更改

this.count = 2

}

}

在演練場中嘗試一(yī)下(xià)

這(zhè)些實例上(shàng)的屬性僅在實例首次創建時(shí)被添加,因此你需要(yào)确保它們都(dōu)出現在 data 函數(shù)返回的對象上(shàng)。若所需的值還未準備好,在必要(yào)時(shí)也可(kě)以使用 null、undefined 或者其他(tā)一(yī)些值占位。

雖然也可(kě)以不在 data 上(shàng)定義,直接向組件實例添加新屬性,但(dàn)這(zhè)個屬性将無法觸發響應式更新。

Vue 在組件實例上(shàng)暴露的內(nèi)置 API 使用 $ 作(zuò)為(wèi)前綴。它同時(shí)也為(wèi)內(nèi)部屬性保留 _ 前綴。因此,你應該避免在頂層 data 上(shàng)使用任何以這(zhè)些字符作(zuò)前綴的屬性。

響應式代理 vs. 原始值 ​

在 Vue 3 中,數(shù)據是基于 JavaScript Proxy(代理) 實現響應式的。使用過 Vue 2 的用戶可(kě)能(néng)需要(yào)注意下(xià)面這(zhè)樣的邊界情況:

js

export default {

data() {

return {

someObject: {}

}

},

mounted() {

const newObject = {}

this.someObject = newObject

console.log(newObject === this.someObject) // false

}

}

當你在賦值後再訪問(wèn) this.someObject,此值已經是原來的 newObject 的一(yī)個響應式代理。與 Vue 2 不同的是,這(zhè)裏原始的 newObject 不會變為(wèi)響應式:請(qǐng)确保始終通(tōng)過 this 來訪問(wèn)響應式狀态。

聲明(míng)方法 ​

要(yào)為(wèi)組件添加方法,我們需要(yào)用到 methods 選項。它應該是一(yī)個包含所有方法的對象:

js

export default {

data() {

return {

count: 0

}

},

methods: {

increment() {

this.count++

}

},

mounted() {

// 在其他(tā)方法或是生命周期中也可(kě)以調用方法

this.increment()

}

}

Vue 自(zì)動為(wèi) methods 中的方法綁定了(le)永遠指向組件實例的 this。這(zhè)确保了(le)方法在作(zuò)為(wèi)事件監聽器或回調函數(shù)時(shí)始終保持正确的 this。你不應該在定義 methods 時(shí)使用箭頭函數(shù),因為(wèi)箭頭函數(shù)沒有自(zì)己的 this 上(shàng)下(xià)文。

js

export default {

methods: {

increment: () => {

// 反例:無法訪問(wèn)此處的 `this`!

}

}

}

和(hé)組件實例上(shàng)的其他(tā)屬性一(yī)樣,方法也可(kě)以在模闆上(shàng)被訪問(wèn)。在模闆中它們常常被用作(zuò)事件監聽器:

template

<button @click="increment">{{ count }}</button>

在演練場中嘗試一(yī)下(xià)

在上(shàng)面的例子中,increment 方法會在 <button> 被點擊時(shí)調用。

DOM 更新時(shí)機 ​

當你更改響應式狀态後,DOM 會自(zì)動更新。然而,你得注意 DOM 的更新并不是同步的。相反,Vue 将緩沖它們直到更新周期的 “下(xià)個時(shí)機” 以确保無論你進行(xíng)了(le)多少(shǎo)次狀态更改,每個組件都(dōu)隻更新一(yī)次。

若要(yào)等待一(yī)個狀态改變後的 DOM 更新完成,你可(kě)以使用 nextTick() 這(zhè)個全局 API:

import { nextTick } from 'vue'

export default {

methods: {

increment() {

this.count++

nextTick(() => {

// 訪問(wèn)更新後的 DOM

})

}

}

}

深層響應性 ​

在 Vue 中,狀态都(dōu)是默認深層響應式的。這(zhè)意味着即使在更改深層次的對象或數(shù)組,你的改動也能(néng)被檢測到。

js

export default {

data() {

return {

obj: {

nested: { count: 0 },

arr: ['foo', 'bar']

}

}

},

methods: {

mutateDeeply() {

// 以下(xià)都(dōu)會按照期望工(gōng)作(zuò)

this.obj.nested.count++

this.obj.arr.push('baz')

}

}

}

你也可(kě)以直接創建一(yī)個淺層響應式對象。它們僅在頂層具有響應性,一(yī)般僅在某些特殊場景中需要(yào)。

有狀态方法 ​

在某些情況下(xià),我們可(kě)能(néng)需要(yào)動态地(dì)創建一(yī)個方法函數(shù),比如(rú)創建一(yī)個預置防抖的事件處理器:

js

import { debounce } from 'lodash-es'

export default {

methods: {

// 使用 Lodash 的防抖函數(shù)

click: debounce(function () {

// ... 對點擊的響應 ...

}, 500)

}

}

不過這(zhè)種方法對于被重用的組件來說是有問(wèn)題的,因為(wèi)這(zhè)個預置防抖的函數(shù)是 有狀态的:它在運行(xíng)時(shí)維護着一(yī)個內(nèi)部狀态。如(rú)果多個組件實例都(dōu)共享這(zhè)同一(yī)個預置防抖的函數(shù),那(nà)麽它們之間(jiān)将會互相影響。

要(yào)保持每個組件實例的防抖函數(shù)都(dōu)彼此獨立,我們可(kě)以改為(wèi)在 created 生命周期鈎子中創建這(zhè)個預置防抖的函數(shù):

js

export default {

created() {

// 每個實例都(dōu)有了(le)自(zì)己的預置防抖的處理函數(shù)

this.debouncedClick = _.debounce(this.click, 500)

},

unmounted() {

// 最好是在組件卸載時(shí)

// 清除掉防抖計時(shí)器

this.debouncedClick.cancel()

},

methods: {

click() {

// ... 對點擊的響應 ...

}

}

}

網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發
下(xià)一(yī)篇:計算屬性
上(shàng)一(yī)篇:模闆語法