基本示例
計算屬性允許我們聲明(míng)性地(dì)計算衍生值。然而在有些情況下(xià),我們需要(yào)在狀态變化時(shí)執行(xíng)一(yī)些“副作(zuò)用”:例如(rú)更改 DOM,或是根據異步操作(zuò)的結果去修改另一(yī)處的狀态。
在選項式 API 中,我們可(kě)以使用 watch 選項在每次響應式屬性發生變化時(shí)觸發一(yī)個函數(shù)。
js
export default {
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每當 question 改變時(shí),這(zhè)個函數(shù)就會執行(xíng)
question(newQuestion, oldQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer()
}
}
},
methods: {
async getAnswer() {
this.answer = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
this.answer = (await res.json()).answer
} catch (error) {
this.answer = 'Error! Could not reach the API. ' + error
}
}
}
}
template
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
watch 選項也支持把鍵設置成用 . 分隔的路徑:
js
export default {
watch: {
// 注意:隻能(néng)是簡單的路徑,不支持表達式。
'some.nested.key'(newValue) {
// ...
}
}
}
深層偵聽器
watch 默認是淺層的:被偵聽的屬性,僅在被賦新值時(shí),才會觸發回調函數(shù)——而嵌套屬性的變化不會觸發。如(rú)果想偵聽所有嵌套的變更,你需要(yào)深層偵聽器:
js
export default {
watch: {
someObject: {
handler(newValue, oldValue) {
// 注意:在嵌套的變更中,
// 隻要(yào)沒有替換對象本身,
// 那(nà)麽這(zhè)裏的 `newValue` 和(hé) `oldValue` 相同
},
deep: true
}
}
}
謹慎使用
深度偵聽需要(yào)遍曆被偵聽對象中的所有嵌套的屬性,當用于大型數(shù)據結構時(shí),開(kāi)銷很(hěn)大。因此請(qǐng)隻在必要(yào)時(shí)才使用它,并且要(yào)留意性能(néng)。
即時(shí)回調的偵聽器
watch 默認是懶執行(xíng)的:僅當數(shù)據源變化時(shí),才會執行(xíng)回調。但(dàn)在某些場景中,我們希望在創建偵聽器時(shí),立即執行(xíng)一(yī)遍回調。舉例來說,我們想請(qǐng)求一(yī)些初始數(shù)據,然後在相關狀态更改時(shí)重新請(qǐng)求數(shù)據。
我們可(kě)以用一(yī)個對象來聲明(míng)偵聽器,這(zhè)個對象有 handler 方法和(hé) immediate: true 選項,這(zhè)樣便能(néng)強制回調函數(shù)立即執行(xíng):
js
export default {
// ...
watch: {
question: {
handler(newQuestion) {
// 在組件實例創建時(shí)會立即調用
},
// 強制立即執行(xíng)回調
immediate: true
}
}
// ...
}
回調函數(shù)的初次執行(xíng)就發生在 created 鈎子之前。Vue 此時(shí)已經處理了(le) data、computed 和(hé) methods 選項,所以這(zhè)些屬性在第一(yī)次調用時(shí)就是可(kě)用的。
回調的觸發時(shí)機
當你更改了(le)響應式狀态,它可(kě)能(néng)會同時(shí)觸發 Vue 組件更新和(hé)偵聽器回調。
默認情況下(xià),用戶創建的偵聽器回調,都(dōu)會在 Vue 組件更新之前被調用。這(zhè)意味着你在偵聽器回調中訪問(wèn)的 DOM 将是被 Vue 更新之前的狀态。
如(rú)果想在偵聽器回調中能(néng)訪問(wèn)被 Vue 更新之後的 DOM,你需要(yào)指明(míng) flush: 'post' 選項:
js
export default {
// ...
watch: {
key: {
handler() {},
flush: 'post'
}
}
}
this.$watch()
我們也可(kě)以使用組件實例的 $watch() 方法來命令式地(dì)創建一(yī)個偵聽器:
js
export default {
created() {
this.$watch('question', (newQuestion) => {
// ...
})
}
}
如(rú)果要(yào)在特定條件下(xià)設置一(yī)個偵聽器,或者隻偵聽響應用戶交互的內(nèi)容,這(zhè)方法很(hěn)有用。它還允許你提前停止該偵聽器。
停止偵聽器
用 watch 選項或者 $watch() 實例方法聲明(míng)的偵聽器,會在宿主組件卸載時(shí)自(zì)動停止。因此,在大多數(shù)場景下(xià),你無需關心怎麽停止它。
在少(shǎo)數(shù)情況下(xià),你的确需要(yào)在組件卸載之前就停止一(yī)個偵聽器,這(zhè)時(shí)可(kě)以調用 $watch() API 返回的函數(shù):
js
const unwatch = this.$watch('foo', callback)
// ...當該偵聽器不再需要(yào)時(shí)
unwatch()
網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發