Vue計(jì)算屬性與偵聽器和過濾器超詳細(xì)介紹
1. 計(jì)算屬性
1.1 使用方法
概述:
模板中放入太多的邏輯會(huì)讓模板過重且難以維護(hù),使用計(jì)算屬性可以讓模板變得簡潔易于維護(hù)。計(jì)算屬性是基于它們的響應(yīng)式依賴進(jìn)行緩存的,計(jì)算屬性比較適合對(duì)多個(gè)變量或者對(duì)象進(jìn)行處理后返回一個(gè)結(jié)果值,也就是數(shù)多個(gè)變量中的某一個(gè)值發(fā)生了變化則我們監(jiān)控的這個(gè)值也就會(huì)發(fā)生變化。
計(jì)算屬性定義在Vue對(duì)象中,通過關(guān)鍵詞computed屬性對(duì)象中定義一個(gè)個(gè)函數(shù),并返回一個(gè)值,使用計(jì)算屬性時(shí)和data中的數(shù)據(jù)使用方式一致。
使用:
當(dāng)不使用計(jì)算屬性時(shí),我們想要計(jì)算模板中的結(jié)果,可以有下面幾種寫法:
<div id="app">
<!-- 方法1:vue在使用時(shí),不推薦在模板中來寫過多的邏輯 -->
<h3>{{ n1+n2 }}</h3>
<!-- 方法2:對(duì)于一個(gè)計(jì)算結(jié)果,可能在當(dāng)前的頁面中,顯示多個(gè),顯示幾次就調(diào)用這個(gè)函數(shù)幾次,性能會(huì)降低 -->
<h3>{{ sum() }}</h3>
<h3>{{ sum() }}</h3>
<h3>{{ sum() }}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2
},
methods: {
sum() {
console.log('sum --- methods');
return this.n1 + this.n2
}
}
})
</script>

如果對(duì)于一個(gè)結(jié)果,進(jìn)行計(jì)算,可以使用vue提供計(jì)算屬性來完成,而且計(jì)算屬性它還具有緩存功能。如果你的依賴項(xiàng),沒有發(fā)生改變,則它會(huì)在再一次調(diào)用時(shí),會(huì)讀取緩存中的數(shù)據(jù)。
<div id="app">
<div>{{total}}</div>
<div>{{total}}</div>
<div>{{total}}</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2
},
// 計(jì)算[屬性]
computed: {
// 調(diào)用時(shí),直接寫名稱就可以,不用寫小括號(hào)
// 計(jì)算屬性中的依賴項(xiàng),可以是一個(gè),也是可以N個(gè),取決于你在計(jì)算屬性中調(diào)用多少
// 注:此方法中不能寫異步
// 簡寫 使用最多的寫法
total() {
console.log('computed -- total')
// 在計(jì)算屬性中,調(diào)用了 n1和n2,則n1和n2就是它的依賴項(xiàng),如果這兩個(gè)依賴項(xiàng),有一個(gè)發(fā)生改變,則它會(huì)重新計(jì)算,如果兩個(gè)都沒有發(fā)生改變,則第2之后調(diào)用,讀取緩存中的數(shù)據(jù)
return this.n1 + this.n2
}
},
methods: {
// 計(jì)算屬性中的方法在 methods 中也可以調(diào)用
sum() {
console.log('sum --- methods', this.total);
return this.n1 + this.n2
}
}
})
</script>
注意:
- 計(jì)算屬性在調(diào)用時(shí),在模板中直接寫名稱就可以,不用寫小括號(hào)。
- 在計(jì)算屬性中,調(diào)用了 n1和n2,則n1和n2就是它的依賴項(xiàng),如果這兩個(gè)依賴項(xiàng),有一個(gè)發(fā)生改變,則它會(huì)重新計(jì)算,如果兩個(gè)都沒有發(fā)生改變,則第2之后調(diào)用,讀取緩存中的數(shù)據(jù)。這也就是為什么上面計(jì)算了3次,卻只調(diào)用了一次計(jì)算方法,因?yàn)橛?jì)算屬性中的依賴項(xiàng)沒有發(fā)生改變。
- 計(jì)算屬性中的依賴項(xiàng),可以是一個(gè),也是可以N個(gè),取決于你在計(jì)算屬性中調(diào)用多少。
- 計(jì)算屬性中的方法中不能寫異步。
- 上面計(jì)算屬性,是簡寫。簡寫是使用最多的方法。
- 計(jì)算屬性不僅可以在模板中調(diào)用,也可以在 method 中調(diào)用。
如果定義的計(jì)算屬性,為簡寫方式,則給計(jì)算屬性賦值時(shí),會(huì)報(bào)錯(cuò)。只有標(biāo)準(zhǔn)的寫法時(shí),它才可以對(duì)于計(jì)算屬性進(jìn)行賦值操作。下面我們就來看一下標(biāo)準(zhǔn)寫法是怎樣的。
<div id="app">
<h3>{{ sum() }}</h3>
<h3>{{msg}}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2,
msg: ''
},
// 計(jì)算[屬性]
computed: {
// 標(biāo)準(zhǔn)寫法
total: {
// 簡寫只是實(shí)現(xiàn)的了標(biāo)準(zhǔn)寫法中的get方法
get() {
return this.n1 + this.n2
},
set(newVal) {
if (newVal > 10) {
this.msg = '值有點(diǎn)的大'
}
}
}
},
methods: {
sum() {
// 賦值只會(huì)觸發(fā)標(biāo)準(zhǔn)方式中的set方法,然后你可以得到它,完成一些別的工作
if (this.total > 6) {
this.total = 101
}
return this.n1 + this.n2
}
}
})
</script>
注意:
- 簡寫方式只是實(shí)現(xiàn)的了標(biāo)準(zhǔn)寫法中的get方法。
- 賦值只會(huì)觸發(fā)標(biāo)準(zhǔn)方式中的set方法,然后你可以得到新的值,完成一些別的工作。
1.2 案例-購物車合計(jì)使用計(jì)算屬性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue學(xué)習(xí)使用</title>
<!-- 第1步: 引入vue庫文件 -->
<script src="./js/vue.js"></script>
</head>
<body>
<!-- 第2步:掛載點(diǎn) -->
<div id="app">
<table border="1" width="600">
<tr>
<th>序號(hào)</th>
<th>名稱</th>
<th>單價(jià)</th>
<th>數(shù)量</th>
<th>操作</th>
</tr>
<tr v-for="item,index in carts">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<button @click="setNum(1,index)">+++</button>
<input type="number" v-model="item.num">
<button @click="setNum(-1,index)">---</button>
</td>
<td>
<button @click="del(index)">刪除</button>
</td>
</tr>
</table>
<hr>
<h3>
合計(jì):
{{totalPrice}}
</h3>
</div>
<!-- 第3步:實(shí)例化vue -->
<script>
const vm = new Vue({
el: '#app',
data: {
carts: [
{ id: 1, name: '小米12pro', price: 1, num: 1 },
{ id: 2, name: '華為手機(jī)', price: 2, num: 1 },
{ id: 3, name: '水果手機(jī)', price: 3, num: 1 },
]
},
methods: {
setNum(n, index) {
this.carts[index].num += n
this.carts[index].num = Math.min(3, Math.max(1, this.carts[index].num))
},
del(index) {
confirm('確定刪除') && this.carts.splice(index, 1)
}
},
// 計(jì)算屬性
computed: {
totalPrice() {
return this.carts.reduce((prev, { price, num }) => {
// 依賴項(xiàng)
prev += price * num
return prev
}, 0)
}
}
})
</script>
</body>
</html>

2. 偵聽器
概述:
使用watch來偵聽data中數(shù)據(jù)的變化,watch中的屬性一定是data 中已經(jīng)存在的數(shù)據(jù)。
當(dāng)需要監(jiān)聽一個(gè)對(duì)象的改變時(shí),普通的watch方法無法監(jiān)聽到對(duì)象內(nèi)部屬性的改變,只有data中的數(shù)據(jù)才能夠監(jiān)聽到變化,此時(shí)就需要deep屬性對(duì)對(duì)象進(jìn)行深度監(jiān)聽。
使用:
標(biāo)準(zhǔn)寫法:
<div id="app">
<div>
<input type="text" v-model="username">
<span>{{errorUsername}}</span>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: '',
errorUsername: ''
},
// 監(jiān)聽器,它用來監(jiān)聽data配置中的數(shù)據(jù)的變化,一但有變化,就會(huì)自動(dòng)觸發(fā).默認(rèn)情況下,初始化不觸發(fā)
// 在監(jiān)聽器中是可以得到this對(duì)象的
// 監(jiān)聽器它的依賴項(xiàng),只有一個(gè),一對(duì)一
// 監(jiān)聽器中可以寫異步
watch: {
// 方法名或?qū)傩悦?就是你要觀察的data中的屬性名稱
// 標(biāo)準(zhǔn)寫法
username: {
// newValue 變化后的值;oldValue 變化前的值
handler(newValue, oldValue) {
if (newValue.length >= 3) this.errorUsername = '賬號(hào)過長'
else this.errorUsername = ''
}
}
})
</script>
注意:
- 監(jiān)聽器用來監(jiān)聽data配置中的數(shù)據(jù)的變化,一但有變化,就會(huì)自動(dòng)觸發(fā).默認(rèn)情況下,初始化不觸發(fā)。
- 在監(jiān)聽器中是可以得到this對(duì)象的。
- 監(jiān)聽器的依賴項(xiàng),只有一個(gè),一對(duì)一。
- 監(jiān)聽器中可以寫異步(Ajax 或者 setTimeout)。
簡寫:
<div id="app">
<div>
<input type="text" v-model="username">
<span>{{errorUsername}}</span>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: '',
errorUsername: ''
},
watch: {
username(newValue, oldValue) {
if (newValue.length >= 3) this.errorUsername = '賬號(hào)過長'
else this.errorUsername = ''
}
}
})
</script>
初始化時(shí),啟用偵聽器寫法:
<div id="app">
<div>
<input type="text" v-model="username">
<span>{{errorUsername}}</span>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
username: 'aaa',
errorUsername: ''
},
watch: {
// 方法名或?qū)傩悦?就是你要觀察的data中的屬性名稱
// 標(biāo)準(zhǔn)寫法
username: {
handler(newValue, oldValue) {
if (newValue.length >= 3) this.errorUsername = '賬號(hào)過長'
else this.errorUsername = ''
},
// 初始時(shí),執(zhí)行1次 --- 一般情況下,不啟用 只有在標(biāo)準(zhǔn)寫法下面,才有此配置
immediate: true
}
})
</script>
注意:這個(gè)配置只有在標(biāo)準(zhǔn)寫法下才能有。
監(jiān)聽對(duì)象中的屬性變化:
<div id="app">
<div>
<input type="number" v-model.number="user.id">
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
user: { id: 100, name: 'aaa' }
},
// 監(jiān)聽對(duì)象中的指定的屬性數(shù)據(jù)的變化 推薦如果你監(jiān)聽的是一個(gè)對(duì)象中數(shù)據(jù)變化,建議這樣的方式
watch: {
'user.id'(newValue, oldValue){
console.log(newValue, oldValue);
}
}
})
</script>

監(jiān)聽對(duì)象變化:
<div id="app">
<div>
<input type="number" v-model.number="user.id">
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
user: { id: 100, name: 'aaa' }
},
watch: {
// 監(jiān)聽對(duì)象,只能使用標(biāo)準(zhǔn)方式來寫
// 監(jiān)聽對(duì)象變化,它的前后值是一樣的,無法區(qū)分
user: {
// 深度監(jiān)聽
deep: true,
handler(newValue, oldValue) {
console.log(newValue, oldValue);
},
}
}
})
</script>
注意:
- 監(jiān)聽對(duì)象,只能使用標(biāo)準(zhǔn)方式來寫
- 監(jiān)聽對(duì)象變化,它的前后值是一樣的,無法區(qū)分
3. 過濾器
概述:
在數(shù)據(jù)被渲染之前,可以對(duì)其進(jìn)行進(jìn)一步處理,比如將字符截取或者將小寫統(tǒng)一轉(zhuǎn)換為大寫等等,過濾器本身就是一個(gè)方法。
過濾器的作用就是為了對(duì)于界面中顯示的數(shù)據(jù)進(jìn)行處理操作。
過濾器可以定義全局或局部。
定義全局過濾器:
<div id="app">
<h3>{{ phone | phoneCrypt }}</h3>
</div>
<script>
// 參數(shù)1:過濾器的名稱,可以隨意起名
// 參數(shù)2:回調(diào)函數(shù),回調(diào)函數(shù)中的參數(shù)最少要有一個(gè),第1位參數(shù),永遠(yuǎn)指向?yàn)橐^濾的數(shù)據(jù)
Vue.filter('phoneCrypt', value => {
return value.slice(0, 3) + '~~~~' + value.slice(7)
})
const vm = new Vue({
el: '#app',
data: {
phone: '13523235235'
}
})
</script>

上面的全局過濾器的回調(diào)函數(shù)中只有一個(gè)參數(shù),我們還可以定義多個(gè)參數(shù):
<div id="app">
<!-- 這里傳的第一個(gè)參數(shù),對(duì)應(yīng)全局過濾器的回調(diào)函數(shù)中定義的第二個(gè)參數(shù) -->
<h3>{{ phone | phoneCrypt('!!!!') }}</h3>
</div>
<script>
Vue.filter('phoneCrypt', (value, salt = '****') => {
return value.slice(0, 3) + salt + value.slice(7)
})
const vm = new Vue({
el: '#app',
data: {
phone: '13523235235'
}
})
</script>

定義局部過濾器:
<div id="app">
<h3>{{ phone | phoneCrypt('!!!!') }}</h3>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
phone: '13523235235'
},
// 局部過濾器
filters:{
phoneCrypt(value, salt = '****'){
return value.slice(0, 3) + salt + value.slice(7)
}
}
})
</script>

到此這篇關(guān)于Vue計(jì)算屬性與偵聽器和過濾器超詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Vue計(jì)算屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue + element ui實(shí)現(xiàn)播放器功能的實(shí)例代碼
這篇文章主要介紹了vue + element ui實(shí)現(xiàn)播放器功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
Vue中的@blur事件 當(dāng)元素失去焦點(diǎn)時(shí)所觸發(fā)的事件問題
這篇文章主要介紹了Vue中的@blur事件 當(dāng)元素失去焦點(diǎn)時(shí)所觸發(fā)的事件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
vue3?組件與API直接使用的方法詳解(無需import)
這篇文章主要介紹了vue3?組件與API直接使用的方法(無需import),主要包括vue3自動(dòng)導(dǎo)入和API的自動(dòng)引入問題,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
vue3中setup語法糖下通用的分頁插件實(shí)例詳解
這篇文章主要介紹了vue3中setup語法糖下通用的分頁插件,實(shí)例代碼介紹了自定義分頁插件:PagePlugin.vue,文中提到了vue3中setup語法糖下父子組件之間的通信,需要的朋友可以參考下2022-10-10
Element-UI el-calendar樣式如何修改日歷
這篇文章主要介紹了Element-UI el-calendar樣式如何修改日歷問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue3.0中給自己添加一個(gè)vue.config.js配置文件
這篇文章主要介紹了vue3.0中給自己添加一個(gè)vue.config.js配置文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Vue.js使用computed屬性實(shí)現(xiàn)數(shù)據(jù)自動(dòng)更新
在Vue組件中,computed屬性是在組件的選項(xiàng)對(duì)象中聲明的,你可以把它們想象成組件的一個(gè)小功能,告訴Vue當(dāng)某些數(shù)據(jù)變化時(shí),如何更新界面,本文給大家介紹了Vue.js使用computed屬性實(shí)現(xiàn)數(shù)據(jù)自動(dòng)更新,需要的朋友可以參考下2024-06-06

