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