大家好,本篇文章我們繼續學習和 Vue 相關的内容,今天我們歸納總結下如何使用 watch 監聽元件中的資料變化,以及 computed 和 watch 的差別。
什麼是 watch,以及如何使用?
watch 是 Vue.js 中用于監聽資料變化的一種機制。它允許我們在資料發生變化時執行特定的操作。
在 Vue 中使用 watch 的方法如下:
1.在 Vue 元件中,定義一個 watch 對象,其中包含要監聽的資料屬性以及對應的回調函數。
watch: {
dataName: function(newValue, oldValue) {
// code
}
}
其中,dataName 是要監聽的資料名稱,newValue 是新的值,oldValue 是舊的值。
2.在 Vue 執行個體中,使用 $watch() 方法進行監聽
vm.$watch('someData', function(newVal, oldVal) {
// do something with newVal
});
注意:watch 回調函數會在偵聽的資料發生變化時立即執行,而 computed 屬性隻有在其依賴的資料發生變化時才會計算。
watch 通常用于監聽一個資料的變化并執行複雜的業務邏輯,例如在某個資料變化後需要進行 HTTP 請求或者調用其他函數。
下面是一個簡單的 watch 的例子:
<template>
<div>
<input v-model="message" type="text" placeholder="請輸入内容">
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
}
},
watch: {
message: function (newVal, oldVal) {
console.log('message changed from ' + oldVal + ' to ' + newVal)
}
},
}
</script>
在這個例子中,我們使用了 watch 來監聽 message 的變化,并在資料變化時列印出更改前後的值。
當然,watch 還可以接收一個對象,其中可以定義多個監聽器。這裡有一個例子,它監聽了多個資料:
watch: {
firstName: function (newVal, oldVal) {
console.log('firstName changed from ' + oldVal + ' to ' + newVal)
},
lastName: function (newVal, oldVal) {
console.log('lastName changed from ' + oldVal + ' to ' + newVal)
}
}
一些進階用法介紹
1、深度觀察 (deep: true):如果你希望對對象内部屬性的變化進行監聽,可以使用 deep: true 選項。
data() {
user: {
name: 'John',
age: 25
}
},
watch: {
'user.name': function (val) {
console.log('user name changed:', val)
}
}
在這個例子中,我們監聽了 user 對象中的 name 屬性,當該屬性變化時,會執行回調函數。
2、設定初始值 (immediate: true):如果你希望 watch 在元件建立時立即執行一次,可以使用 immediate: true 選項。
data() {
count: 0
},
watch: {
count: {
handler: function (val, oldVal) {
console.log('count changed');
},
immediate: true
}
}
3、異步處理 (handler):watch 的回調函數是異步執行的,這意味着如果有多個值在短時間内發生變化,回調函數隻會在這些變化結束後執行一次。
watch: {
searchText: function (val) {
this.searching = true
setTimeout(() => {
this.searchData(val)
this.searching = false
}, 500)
}
}
在這個例子中,我們監聽了 searchText 屬性,并在資料變化後延遲 500 毫秒執行搜尋操作。
4、使用 watch 觀察器實作自動儲存
data() {
content: ''
},
watch: {
content: function (val) {
localStorage.setItem('content', val)
}
}
在這個例子中,我們監聽了 content 屬性,并在資料變化時自動儲存到本地存儲中。
應用場景介紹
watch 監聽器還有許多其他的應用場景,例如:
- 在表單輸入時進行驗證,并顯示錯誤消息
- 在表格中進行排序和過濾
- 在地圖上實時顯示使用者位置
- 監聽路由變化并執行相應操作
- 監聽視窗大小變化并調整布局
- 監聽滾動事件并實作懶加載
- ……
1.在表單輸入時進行驗證,并顯示錯誤消息
<template>
<form>
<label>
Email:
<input v-model="email" @keyup="validateEmail"/>
</label>
<p v-if="error">{{ error }}</p>
</form>
</template>
<script>
export default {
data() {
return {
email: '',
error: ''
}
},
watch: {
email: {
immediate: true,
handler(val) {
if (!val.includes('@')) {
this.error = 'Invalid email address'
} else {
this.error = ''
}
}
}
}
}
</script>
2.在地圖上實時顯示使用者位置
<template>
<div>
<div id="map"></div>
</div>
</template>
<script>
export default {
data() {
return {
userLocation: {
lat: 0,
lng: 0
},
map: null
}
},
mounted() {
this.map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 0, lng: 0 },
zoom: 8
});
navigator.geolocation.getCurrentPosition(position => {
this.userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
});
},
watch: {
userLocation: {
deep: true,
handler(val) {
this.map.setCenter(val);
new google.maps.Marker({
position: val,
map: this.map
});
}
}
}
}
</script>
在這個示例中,我們使用了 watch 來監聽 userLocation 的變化,在使用者位置發生變化時,使用 setCenter 方法将地圖中心設定為使用者目前位置,并使用 google maps API 在地圖上添加一個标記,顯示使用者目前位置。
注意:這個例子需要引入 google maps 的 js 檔案。
3、監聽路由變化并執行相應操作
<template>
<!-- 省略 -->
</template>
<script>
export default {
watch: {
$route(to, from) {
// 根據路由變化執行相應操作
if (to.path === '/home') {
this.getHomeData()
} else if (to.path === '/about') {
this.getAboutData()
}
}
},
methods: {
getHomeData() {
// 擷取首頁資料
},
getAboutData() {
// 擷取關于頁資料
}
}
}
</script>
4、監聽視窗大小變化并調整布局
<template>
<!-- 省略 -->
</template>
<script>
export default {
data() {
return {
windowWidth: 0
}
},
created() {
this.windowWidth = window.innerWidth
},
watch: {
windowWidth(newWidth, oldWidth) {
// 監聽視窗大小變化并調整布局
if (newWidth < 768) {
// 小螢幕布局
} else {
// 大螢幕布局
}
}
},
mounted() {
window.addEventListener('resize', () => {
this.windowWidth = window.innerWidth
})
}
}
</script>
5、監聽滾動事件并實作懶加載
<template>
<div class="container" ref="container" @scroll="handleScroll">
<img v-for="(item, index) in images" :key="index" :src="item.src" v-show="item.isLoaded" />
</div>
</template>
<script>
export default {
data() {
return {
images: [
{ src: 'image1.jpg', isLoaded: false },
{ src: 'image2.jpg', isLoaded: false },
{ src: 'image3.jpg', isLoaded: false },
// ...
]
}
},
mounted() {
// 初始化加載第一屏圖檔
this.lazyLoad();
},
methods: {
handleScroll() {
this.lazyLoad();
},
lazyLoad() {
const container = this.$refs.container;
const imageList = Array.from(container.querySelectorAll('img'));
// 周遊圖檔清單,如果圖檔進入了可視區域,就加載
imageList.forEach(img => {
if (this.isInViewport(img)) {
img.src = img.dataset.src;
img.isLoaded = true;
}
});
},
isInViewport(img) {
// 擷取圖檔相對于視口的位置
const rect = img.getBoundingClientRect();
// 判斷圖檔是否進入了可視區域
return rect.top < window.innerHeight && rect.bottom > 0;
}
},
watch: {
images: {
handler: function(newVal, oldVal) {
// 每當圖檔加載完成時,就移除已加載圖檔的 isLoaded 屬性
newVal.forEach((item, index) => {
if (item.isLoaded) {
this.$set(this.images[index], 'isLoaded', false);
}
});
},
deep: true
}
}
}
</script>
注意:需要注意的是,在這個案例中,因為images數組中的對象被改變了,是以需要設定deep: true來監聽對象
總之,watch 是一個非常強大和靈活的功能,它可以在資料變化時執行任何操作,并且可以與 computed 計算屬性配合使用,來實作更複雜的邏輯。
computed 和 watch 的差別
watch和computed都可以監聽Vue執行個體中的資料變化,但是它們有着明顯的不同。
watch | computed |
用于監聽某個特定的資料變化。 | 用于計算屬性,可以計算出一個新的值。 |
每次資料變化都會觸發回調函數。 | 僅在相關依賴發生改變時才會觸發重新計算。 |
适用于異步操作或複雜邏輯。 | 适用于簡單計算。 |
不可以在HTML模闆中使用 | 可以在HTML模闆中使用 |
沒有傳回值 | 有傳回值/getter |
可以修改data中的資料 | 也可以使用setters 修改 data 中的資料 |
總之,如果你需要在資料變化時執行異步操作或複雜邏輯,使用watch是更好的選擇;如果你需要在資料變化時計算出一個新值,使用computed是更好的選擇。
關于watch的性能
watch的性能取決于你的代碼實作方式和監聽的資料量。
- 監聽的資料量:如果你監聽了大量的資料,那麼 watch 的性能可能會受到影響。
- 代碼實作:如果你在 watch 回調函數中執行了複雜的邏輯或異步操作,那麼 watch 的性能可能會受到影響。
- 如果你隻是需要在資料變化時執行一些簡單的操作,那麼 watch 的性能應該是可以接受的。
是以,在使用watch時,應該注意監聽的資料量,并且在watch回調函數中盡量少執行複雜的邏輯.總之,watch監聽資料更新并執行回調函數,性能會受到監聽資料量和回調函數實作方式的影響,如果有性能問題,應該優化監聽的資料量和回調函數的實作方式.
結束
今天的文章就介紹到這裡,關于 watch 的用法你學會了,希望今天的文章能幫助到你,感謝你的閱讀。如果你喜歡我的分享,别忘了點贊轉發,讓更多的人看到,最後别忘記點個關注,你的支援将是我分享最大的動力,後續我會持續輸出更多内容,敬請期待。
推薦閱讀
Vue3 學習筆記,Vue 簡介及如何引入 Vue3 架構(一)
Vue3 學習筆記,快速初始化Vue項目及 data 函數用法學習(二)
Vue3 學習筆記,如何定義事件以及如何了解響應式(三)
Vue3 學習筆記,如何了解 computed 計算屬性(四)