大家好,本篇文章我們繼續學習和 Vue 相關的內容,今天我們歸納總結下如何使用 watch 監聽組件中的數據變化,以及 computed 和 watch 的區別。
watch 是 Vue.js 中用于監聽數據變化的一種機制。它允許我們在數據發生變化時執行特定的操作。
在 Vue 中使用 watch 的方法如下:
在 Vue 組件中,定義一個 watch 對象,其中包含要監聽的數據屬性以及對應的回調函數。
watch: { dataName: function(newValue, oldValue) { // code }}
其中,dataName 是要監聽的數據名稱,newValue 是新的值,oldValue 是舊的值。
在 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) }}
深度觀察 (deep: true):如果你希望對對象內部屬性的變化進行監聽,可以使用 deep: true 選項。
data() { user: { name: 'John', age: 25 }},watch: { 'user.name': function (val) { console.log('user name changed:', val) }}
在這個例子中,我們監聽了 user 對象中的 name 屬性,當該屬性變化時,會執行回調函數。
設置初始值 (immediate: true):如果你希望 watch 在組件創建時立即執行一次,可以使用 immediate: true 選項。
data() { count: 0},watch: { count: { handler: function (val, oldVal) { console.log('count changed'); }, immediate: true }}
異步處理 (handler):watch 的回調函數是異步執行的,這意味著如果有多個值在短時間內發生變化,回調函數只會在這些變化結束后執行一次。
watch: { searchText: function (val) { this.searching = true setTimeout(() => { this.searchData(val) this.searching = false }, 500) }}
在這個例子中,我們監聽了 searchText 屬性,并在數據變化后延遲 500 毫秒執行搜索操作。
使用 watch 觀察器實現自動保存。
data() { content: ''},watch: { content: function (val) { localStorage.setItem('content', val) }}
在這個例子中,我們監聽了 content 屬性,并在數據變化時自動保存到本地存儲中。
watch 監聽器還有許多其他的應用場景,例如:
<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>
<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 文件。
<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>
<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>
<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 計算屬性配合使用,來實現更復雜的邏輯。
watch和computed都可以監聽Vue實例中的數據變化,但是它們有著明顯的不同。
watch | computed |
用于監聽某個特定的數據變化。 | 用于計算屬性,可以計算出一個新的值。 |
每次數據變化都會觸發回調函數。 | 僅在相關依賴發生改變時才會觸發重新計算。 |
適用于異步操作或復雜邏輯。 | 適用于簡單計算。 |
不可以在HTML模板中使用 | 可以在HTML模板中使用 |
沒有返回值 | 有返回值/getter |
可以修改data中的數據 | 也可以使用setters 修改 data 中的數據 |
總之,如果你需要在數據變化時執行異步操作或復雜邏輯,使用watch是更好的選擇;如果你需要在數據變化時計算出一個新值,使用computed是更好的選擇。
watch的性能取決于你的代碼實現方式和監聽的數據量。
所以,在使用watch時,應該注意監聽的數據量,并且在watch回調函數中盡量少執行復雜的邏輯.總之,watch監聽數據更新并執行回調函數,性能會受到監聽數據量和回調函數實現方式的影響,如果有性能問題,應該優化監聽的數據量和回調函數的實現方式.
今天的文章就介紹到這里,關于 watch 的用法你學會了,希望今天的文章能幫助到你,感謝你的閱讀。
本文鏈接:http://www.tebozhan.com/showinfo-26-45498-0.htmlVue3 學習筆記,如何使用 Watch 監聽數據變化
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com