上一節我們簡單的介紹了一下vue3 項目中的計算屬性,這一節我們繼續 vue3 的基礎知識講解。
這一節我們來說 vue3 的偵聽器。
學過 vue2 的小伙伴們肯定學習過偵聽器,主要是用來監聽頁面數據或者是路由的變化,來執行相應的操作,在 vue3里面呢,也有偵聽器的用法,功能基本一樣,換湯不換藥的東西。 偵聽器是常用的 Vue API 之一,它用于監聽一個數據并在數據變動時做一些自定義邏輯,本文將先列舉偵聽器在 Vue 中的使用方式,然后再分析源碼講述為什么可以這樣使用、以及偵聽器的實現原理。下面我們稍微說一下偵聽器。
watch 偵聽器使用。
watch API 使用,至少需要指定兩個參數:source 和callback,其中 callback 被明確指定只能為函數,所以不同是用方式的差別其實只在 source 。
接下來我們看一下 vue3 偵聽器的基本使用:
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num" /> <br> <br> <el-button type="primary" @click="num++">num + 1</el-button> </div> </template> <script> import { watch, ref } from 'vue' export default { setup() { const num = ref(1) watch(num, (newVal, oldVal) => { console.log("新值:", newVal, " 舊值:", oldVal) }) return { num, } } } </script> <style scoped> .el-input { width: 100px; } </style>
上面的代碼是頁面上有一個數字,點擊按鈕一下,數字加一,然后偵聽器偵聽數字的變化,打印出偵聽的最新值和老值。
OK。上邊的案例就是 vue3 偵聽器的簡單案例,偵聽器和計算屬性一樣,可以創建多個偵聽器,這個是沒有問題的,案例就不寫了,和上一節講的聲明多個計算屬性是一致的。如果有不明白的可以看一下我的上一篇博客。
上邊我們說過這么一句話,watch API 至少需要指定兩個參數: source 和 callback。通過上邊的案例我們看到了, 確實是兩個,source 是監聽的數據,callback 是監聽回調,那為啥說是至少呢?
對的,因為他還有第三個參數 ——配置對象。
在 vue2 里面,我們打開頁面就像讓偵聽器立即執行,而不是在第一次數據改變的時候才開始執行,這時候有一個參數叫immediate,設置了這個參數,創建第一次就執行,所以說呢,vue3 同樣可以使用。
上面的案例刷新執行的時候發現,在點擊按鈕之前,也就是 num 創建的時候,偵聽器是沒有執行的,所以說呢,加上 immediate 參數,就可以讓偵聽器立即執行操作。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num" /> <br> <br> <el-button type="primary" @click="num++">num + 1</el-button> </div> </template> <script> import { watch, ref } from 'vue' export default { setup() { const num = ref(1) watch(num, (newVal, oldVal) => { console.log("新值:", newVal, " 舊值:", oldVal) }, { immediate: true }) return { num, } } } </script> <style scoped> .el-input { width: 100px; } </style>
我們看到,刷新完頁面,還沒有點擊按鈕讓 num 加一的,控制臺就有數據打印了,為什么呢?就是因為我們加了 immediate 為 true,讓偵聽器立即執行。控制臺輸出最新的值也就是我們初始化的值1,老的值沒有,所以輸出了 undefined。
偵聽器監聽 reactive
上面說了偵聽器偵聽單個數據,他也可以用來偵聽對象的變化。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.age" /> <br> <br> <el-button type="primary" @click="num.age++">num + 1</el-button> </div> </template> <script> import { watch, ref, reactive } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10 }) watch(num, (newVal, oldVal) => { console.log(newVal, oldVal) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
比如說上面代碼,我們偵聽 num 這個對象的變化。
看效果我們發下,在監聽整個 reactive 響應式對象的時候,確實當里面的屬性值發生改變了之后可以被偵聽器檢測到,但是 newVal 和 oldVal 的值都是新的,默認是10,點擊之后,新值是 11 很正常,但是老值不應該是 10 嗎?為什么這里老值和新值一樣也是 11 呢?
這個不需要疑問哈,如果監聽整個 reactive 數據的話,只能回調到最新的值,獲取不到老的值。
那問題來嘍,我就修改 age 屬性,我就要獲取 age 老的值怎么辦?其實我們只需要監聽 num 下面的 age 就可以了,先看下面的代碼哈。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.age" /> <br> <br> <el-button type="primary" @click="num.age++">num + 1</el-button> </div> </template> <script> import { watch, ref, reactive } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10 }) watch(num.age, (newVal, oldVal) => { console.log(newVal, oldVal) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
我們監聽對象直接是 num.age, 監聽年齡屬性值,保存看一下效果。
刷新結果我們可以看到哈,我們啥都沒干,偵聽器直接報了一個警告給我們,啥意思呢,其實不能直接這樣監聽。
當我們需要監聽某個對象屬性的時候,我們不能直接對象點屬性的方式進行監聽,需要傳入一個 getter 方法,也就是箭頭函數進行監聽,下面的代碼是正確方式哈。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.age" /> <br> <br> <el-button type="primary" @click="num.age++">num + 1</el-button> </div> </template> <script> import { watch, ref, reactive } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10 }) watch(() => num.age, (newVal, oldVal) => { console.log(newVal, oldVal) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
OK,保存刷新,我們發現,偵聽器已經不報錯了,而且我們點擊按鈕讓 age 加一的時候,可以順利的監聽到 age 的變化,并且回調出最新值和上一次的值。
通過箭頭函數,我們就可以實現對象屬性的監聽。
很多人說,vue2 在監聽對象的時候需要對偵聽器設置深度偵聽,為什么 vue3 這個不需要呢?因為他監聽響應式對象,默認就是深度監聽。但是,如果監聽的是深度嵌套對象或數組中的 property 變化時,仍然需要 deep 選項設置為 true。
看下面的案例,我們監聽深層嵌套的 time 屬性值。其實我覺得沒大必要,不使用箭頭函數其實可以。但是還是寫一下吧。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.todo.time" /> <br> <br> <el-button type="primary" @click="num.todo.time ++">num.todo.time + 1</el-button> </div> </template> <script> import { watch, ref, reactive, computed, } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10, todo: { name: '彈吉他', time: 1 } }) watch(() => num, (newVal, oldVal) => { console.log(newVal.todo.time, oldVal.todo.time) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
保存代碼刷新,發現點擊之后沒有監聽到。
這個時候就可以加上 deep 深度監聽。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.todo.time" /> <br> <br> <el-button type="primary" @click="num.todo.time ++">num.todo.time + 1</el-button> </div> </template> <script> import { watch, ref, reactive, computed, } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10, todo: { name: '彈吉他', time: 1 } }) watch(() => num, (newVal, oldVal) => { console.log(newVal.todo.time, oldVal.todo.time) }, { deep: true }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
加上深度監聽{ deep:true }
我們可以看到打印出信息來了,其實我覺得這個方法有點多余,但是萬一用到呢是吧?啊哈哈哈哈,自己根據情況選擇使用吧。
但是有一點要注意哈!深度偵聽需要遍歷被偵聽對象中的所有嵌套的 屬性,當用于大型數據結構時,開銷很大。因此請只在必要時才使用它,并且要留意性能。
監聽多個參數執行各自邏輯
本來不打算說了,但是逼逼賴賴這么久了,稍微簡單提一下吧。
比如說我們需要監聽多個參數,假設兩個哈,然后每個參數監聽到之后,執行的邏輯是不一樣的,我們可以創建多個偵聽器來分別監聽,不寫全部代碼了,只寫關鍵代碼了哈。
// 第一個 watch(num, (newVal, oldVal) => { console.log(newVal, oldVal) }) // 第二個 watch(()=> boy.age, (newVal, oldVal) => { console.log(newVal, oldVal) })
監聽多個參數執行相同邏輯
這個的意思就是無論是 num 改變還是 boy.age 改變,我執行的代碼都是一樣的。看下面案例:
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.name" /> <el-input v-model="num.age" /> <br> <br> <el-button type="primary" @click="num.todo.time ++">num.todo.time + 1</el-button> </div> </template> <script> import { watch, ref, reactive, computed, } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10, todo: { name: '彈吉他', time: 1 } }) watch([() => num.name, () => num.age], (newVal, oldVal) => { console.log(newVal, oldVal) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
保存刷新頁面,修改 name 和 age 的值。
上面我們把數據源以數組的方式傳入,返回的回調參數,新值和舊值都是以數組的方式返回,新值舊值的數組內順序就是我們數據源傳入的順序,都能看出來哈。
如果你不想讓他返回數組你可以這樣改一下,其實都差不多,了解一下,根據實際情況選擇性使用就行。
<template> <div> <h1>watch 偵聽器</h1> <el-input v-model="num.name" /> <el-input v-model="num.age" /> <br> <br> <el-button type="primary" @click="num.todo.time ++">num.todo.time + 1</el-button> </div> </template> <script> import { watch, ref, reactive, computed, } from 'vue' export default { setup() { const num = reactive({ name: '我是????????.', age: 10, todo: { name: '彈吉他', time: 1 } }) watch([() => num.name, () => num.age], ([newName, newAge], [oldName, oldAge]) => { console.log(newName, newAge, oldName, oldAge) }) return { num } } } </script> <style scoped> .el-input { width: 100px; } </style>
保存刷新查看一下效果。
有關Vue3中偵聽器watch的使用教程內容已全部講述完畢,歡迎關注后續更多精彩內容。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/130352.html
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:提問深度與非深度的區別對象與數組與的區別的一個特點是,最初綁定的時候是不會執行的,要等到改變時才執行監聽計算。為一個對象,鍵是需要觀察的表達式,值是對應回調函數。值也可以是方法名,或者包含選項的對象適用場景一個數據影響多個數據。 提問 1.深度watch與非深度watch的區別;2.watch對象與數組;3.watch與computed的區別; immediate FullNa...
摘要:狀態管理社區當前最流行的狀態管理方案分別是單向數據流的和基于的。目前的現狀主要是由于并沒有將其底層的曝光出來。是一個開源項目,完全兼容的,擁簇面向未來編程,致力于加速未來生態圈的建設。 概要 Vue 的作者尤雨溪最近公布了 3.0 版本最重要的 RFC Vue Function-based API。在 React 推出 Hooks 后不久,Vue 社區也迎來了自己的組件邏輯復用機制。 ...
閱讀 546·2023-03-27 18:33
閱讀 731·2023-03-26 17:27
閱讀 630·2023-03-26 17:14
閱讀 590·2023-03-17 21:13
閱讀 519·2023-03-17 08:28
閱讀 1800·2023-02-27 22:32
閱讀 1291·2023-02-27 22:27
閱讀 2176·2023-01-20 08:28