Vue.js中關(guān)于偵聽(tīng)器(watch)的高級(jí)用法示例
Vue偵聽(tīng)器watch
雖然計(jì)算屬性在大多數(shù)情況下更合適,但有時(shí)也需要一個(gè)自定義的偵聽(tīng)器。這就是為什么 Vue 通過(guò) watch 選項(xiàng)提供了一個(gè)更通用的方法,來(lái)響應(yīng)數(shù)據(jù)的變化。當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開(kāi)銷較大的操作時(shí),這個(gè)方式是最有用的。例如:
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<!-- 因?yàn)?AJAX 庫(kù)和通用工具的生態(tài)已經(jīng)相當(dāng)豐富,Vue 核心代碼沒(méi)有重復(fù) -->
<!-- 提供這些功能以保持精簡(jiǎn)。這也可以讓你自由選擇自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 發(fā)生改變,這個(gè)函數(shù)就會(huì)運(yùn)行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
// `_.debounce` 是一個(gè)通過(guò) Lodash 限制操作頻率的函數(shù)。
// 在這個(gè)例子中,我們希望限制訪問(wèn) yesno.wtf/api 的頻率
// AJAX 請(qǐng)求直到用戶輸入完畢才會(huì)發(fā)出。想要了解更多關(guān)于
// `_.debounce` 函數(shù) (及其近親 `_.throttle`) 的知識(shí),
// 請(qǐng)參考:https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this // this重定向
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
// 這是我們?yōu)榕卸ㄓ脩敉V馆斎氲却暮撩霐?shù)
500
)
}
})
</script>
偵聽(tīng)器(watch)的高級(jí)用法
假設(shè)有如下代碼:
<div>
<p>FullName: {{fullName}}</p>
<p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
el: '#root',
data: {
firstName: 'Dawei',
lastName: 'Lou',
fullName: ''
},
watch: {
firstName(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
}
}
})
上面的代碼的效果是,當(dāng)我們輸入firstName后,wacth監(jiān)聽(tīng)每次修改變化的新值,然后計(jì)算輸出fullName。
handler方法和immediate屬性
這里 watch 的一個(gè)特點(diǎn)是,最初綁定的時(shí)候是不會(huì)執(zhí)行的,要等到 firstName 改變時(shí)才執(zhí)行監(jiān)聽(tīng)計(jì)算。那我們想要一開(kāi)始就讓他最初綁定的時(shí)候就執(zhí)行改怎么辦呢?我們需要修改一下我們的 watch 寫法,修改過(guò)后的 watch 代碼如下:
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里聲明了firstName這個(gè)方法之后立即先去執(zhí)行handler方法
immediate: true
}
}
注意到handler了嗎,我們給 firstName 綁定了一個(gè)handler方法,之前我們寫的 watch 方法其實(shí)默認(rèn)寫的就是這個(gè)handler,Vue.js會(huì)去處理這個(gè)邏輯,最終編譯出來(lái)其實(shí)就是這個(gè)handler。
而immediate:true代表如果在 wacth 里聲明了 firstName 之后,就會(huì)立即先去執(zhí)行里面的handler方法,如果為 false就跟我們以前的效果一樣,不會(huì)在綁定的時(shí)候就執(zhí)行。
deep屬性
watch 里面還有一個(gè)屬性 deep,默認(rèn)值是 false,代表是否深度監(jiān)聽(tīng),比如我們 data 里有一個(gè)obj屬性:
<div>
<p>obj.a: {{obj.a}}</p>
<p>obj.a: <input type="text" v-model="obj.a"></p>
</div>
new Vue({
el: '#root',
data: {
obj: {
a: 123
}
},
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true
}
}
})
當(dāng)我們?cè)谠谳斎肟蛑休斎霐?shù)據(jù)視圖改變obj.a的值時(shí),我們發(fā)現(xiàn)是無(wú)效的。受現(xiàn)代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測(cè)到對(duì)象屬性的添加或刪除。由于 Vue 會(huì)在初始化實(shí)例時(shí)對(duì)屬性執(zhí)行 getter/setter 轉(zhuǎn)化過(guò)程,所以屬性必須在 data 對(duì)象上存在才能讓 Vue 轉(zhuǎn)換它,這樣才能讓它是響應(yīng)的。
默認(rèn)情況下 handler 只監(jiān)聽(tīng)obj這個(gè)屬性它的引用的變化,我們只有給obj賦值的時(shí)候它才會(huì)監(jiān)聽(tīng)到,比如我們?cè)?mounted事件鉤子函數(shù)中對(duì)obj進(jìn)行重新賦值:
mounted: {
this.obj = {
a: '456'
}
}
這樣我們的 handler 才會(huì)執(zhí)行,打印obj.a changed。
相反,如果我們需要監(jiān)聽(tīng)obj里的屬性a的值呢?這時(shí)候deep屬性就派上用場(chǎng)了!
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
deep: true
}
}
deep的意思就是深入觀察,監(jiān)聽(tīng)器會(huì)一層層的往下遍歷,給對(duì)象的所有屬性都加上這個(gè)監(jiān)聽(tīng)器,但是這樣性能開(kāi)銷就會(huì)非常大了,任何修改obj里面任何一個(gè)屬性都會(huì)觸發(fā)這個(gè)監(jiān)聽(tīng)器里的 handler。
優(yōu)化,我們可以是使用字符串形式監(jiān)聽(tīng)。
watch: {
'obj.a': {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
// deep: true
}
}
這樣Vue.js才會(huì)一層一層解析下去,直到遇到屬性a,然后才給a設(shè)置監(jiān)聽(tīng)函數(shù)。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
詳解利用eventemitter2實(shí)現(xiàn)Vue組件通信
這篇文章主要介紹了詳解利用eventemitter2實(shí)現(xiàn)Vue組件通信,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
vue select組件的使用與禁用實(shí)現(xiàn)代碼
這篇文章主要介紹了vue--select組件的使用與禁用的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值 ,需要的朋友可以參考下2018-04-04
vue2封裝webSocket的實(shí)現(xiàn)(開(kāi)箱即用)
在Vue2中,可以使用WebSocket實(shí)時(shí)通信,本文主要介紹了vue2封裝webSocket的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
Vue2?響應(yīng)式系統(tǒng)之?dāng)?shù)組
這篇文章主要介紹了Vue2?響應(yīng)式系統(tǒng)之?dāng)?shù)組,本文接著上幾篇文章Vue2響應(yīng)式系統(tǒng)?、Vue2?響應(yīng)式系統(tǒng)之分支切換,響應(yīng)式系統(tǒng)之嵌套、響應(yīng)式系統(tǒng)之深度響應(yīng)?展開(kāi)相關(guān)內(nèi)容,需要的朋友可以參考一下2022-04-04
詳解如何搭建mpvue框架搭配vant組件庫(kù)的小程序項(xiàng)目
這篇文章主要介紹了詳解如何搭建mpvue框架搭配vant組件庫(kù)的小程序項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
Vue實(shí)現(xiàn)Excel預(yù)覽功能使用場(chǎng)景示例詳解
這篇文章主要為大家介紹了Vue實(shí)現(xiàn)Excel預(yù)覽功能使用場(chǎng)景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09

