computed
不使用 computed
通過簡單的字串拼接
import Vue from 'vue'
new Vue({
el: '#root',
template: `
<div>
<span>Name: {{firstName + ' ' + lastName}}</span>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou'
}
})
複製程式碼
使用 computed
new Vue({
el: '#root',
template: `
<div>
<span>Name: {{name}}</span>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou'
},
computed: {
name () {
return `${this.firstName} ${this.lastName}`
}
}
})
複製程式碼
使用 methods
顯示結果和使用 computed 相同
new Vue({
el: '#root',
template: `
<div>
<span>Name: {{name}}</span>
<span>Name: {{getName()}}</span>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou'
},
computed: {
name () {
return `${this.firstName} ${this.lastName}`
}
},
methods: {
getName () {
return `${this.firstName} ${this.lastName}`
}
}
})
複製程式碼
使用 computed 的好處
當我們改變 number 時,整個應用會重新渲染,vue 會被資料重新渲染到 dom 中。這時,如果我們使用 getName 方法,隨著渲染,方法也會被呼叫,而 computed 不會重新進行計算,從而效能開銷比較小。當新的值需要大量計算才能得到,快取的意義就非常大。
如果 computed 所依賴的資料發生改變時,計算屬性才會重新計算,並進行快取;當改變其他資料時,computed 屬性 並不會重新計算,從而提升效能。
當我們拿到的值需要進行一定處理使用時,就可以使用 computed。
import Vue from 'vue'
new Vue({
el: '#root',
template: `
<div>
<p>Name: {{name}}</p>
<p>Name: {{getName()}}</p>
<p>Number: {{number}}</p>
<p><input type="text" v-model="number"/></p>
<p>FirsName: <input type="text" v-model="firstName"/></p>
<p>LaseName: <input type="text" v-model="lastName"/></p>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou',
number: 0
},
computed: {
name () {
console.log('new name')
return `${this.firstName} ${this.lastName}`
}
},
methods: {
getName () {
console.log('getName invoked')
return `${this.firstName} ${this.lastName}`
}
}
})
複製程式碼
computed 設定的操作
通過 computed 的 set 方法,可以進行設定的操作。
如下例,通過改變 name 的值,也可以改變 computed 屬性 name 所以來的 firstName 和 lastName 的值。
不推薦這樣做,一般 computed 屬性資料是根據多重資料組合成的新的資料,組合容易,但拆開重新設定並不容易
template: `
<div>
<p>Name: <input type="text" v-model="name"/></p>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou',
},
computed: {
name: {
get () {
console.log('new name')
return `${this.firstName} ${this.lastName}`
},
set (name) {
const names = name.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
複製程式碼
watch
例如,監聽 firstName 資料,並根據改變得到的新值,進行某些操作。
new Vue({
template: `
<div>
<p>FullName: {{fullName}}</p>
<p>FirsName: <input type="text" v-model="firstName"/></p>
</div>
`,
data: {
firstName: 'Jokcy',
lastName: 'Lou',
fullName: ' '
},
watch: {
firstName (newName, oldName) {
this.fullName = newName + ' ' + this.lastName
}
}
})
複製程式碼
注意:上例中,初始 fullName 是沒有值的,只有當資料改變時,才會顯示。因為 watch 的方法預設是不會執行的,只有當監聽資料變化,才會執行。
immerdiate 屬性
通過宣告 immediate 選項為 true,可以立即執行一次 handler。
watch: {
firstName: {
handler (newName, oldName) {
this.fullName = newName + ' ' + this.lastName
},
immediate: true
}
},
複製程式碼
watch 並不適用於顯示某一個資料以及資料的拼裝等。watch 用在監聽資料變化,做某些指令操作(給後臺發資料請求)
deep屬性
不使用 deep 時,當我們改變 obj.a 的值時,watch不能監聽到資料變化,預設情況下,handler 只監聽屬性引用的變化,也就是隻監聽了一層,但改物件內部的屬性是監聽不到的。
new Vue({
template: `
<div>
<p>Obj.a: <input type="text" v-model="obj.a"/></p>
</div>
`,
data: {
obj: {
a: '123'
}
},
watch: {
obj: {
handler () {
console.log('obj.a changed')
},
immediate: true
// deep: true
}
}
})
複製程式碼
通過使用 deep: true 進行深入觀察,這時,我們監聽 obj,會把 obj 下面的屬性層層遍歷,都加上監聽事件,這樣做,效能開銷也會變大,只要修改 obj 中任意屬性值,都會觸發 handler。
如何優化?
在字串中,寫 obj 深入的屬性呼叫,vue 會層層解析,找到 a,並進行監聽。
watch: {
'obj.a': {
handler () {
console.log('obj.a changed')
},
immediate: true
// deep: true
}
}
複製程式碼
注意
不要在 computed 或 watch 中,去修改所依賴的資料的值,尤其是 computed;如果這樣做,可能導致一個無線迴圈的觸發。