Vue中watch與watchEffect的區(qū)別詳細(xì)解讀
watch和watchEffect的對比
watch函數(shù)與watchEffect函數(shù)都是監(jiān)聽器,在寫法和用法上有一定區(qū)別,是同一功能的兩種不同形態(tài),底層都是一樣的。
watch
watch顯式指定依賴數(shù)據(jù),依賴數(shù)據(jù)更新時(shí)執(zhí)行回調(diào)函數(shù)
具有一定的惰性lazy 第一次頁面展示的時(shí)候不會執(zhí)行,只有數(shù)據(jù)變化的時(shí)候才會執(zhí)行(設(shè)置immediate: true時(shí)可以變?yōu)榉嵌栊?,頁面首次加載就會執(zhí)行)
監(jiān)視r(shí)ef定義的響應(yīng)式數(shù)據(jù)時(shí)可以獲取到原值既要指明監(jiān)視的屬性,也要指明監(jiān)視的回調(diào)
watchEffect
watchEffect自動(dòng)收集依賴數(shù)據(jù),依賴數(shù)據(jù)更新時(shí)重新執(zhí)行自身
立即執(zhí)行,沒有惰性,頁面的首次加載就會執(zhí)行
無法獲取到原值,只能得到變化后的值
不用指明監(jiān)視哪個(gè)屬性,監(jiān)視的回調(diào)中用到哪個(gè)屬性就監(jiān)視哪個(gè)屬性
深度解析watch函數(shù)
watch函數(shù)有兩個(gè)小坑:
- 監(jiān)視r(shí)eactive定義的響應(yīng)式數(shù)據(jù)(該數(shù)據(jù)為一個(gè)對象,因?yàn)閞eactive只能定義數(shù)組或?qū)ο箢愋偷捻憫?yīng)式)時(shí):oldValue無法正確獲取,會強(qiáng)制開啟深度監(jiān)視,deep配置不生效。
- 監(jiān)視r(shí)eactive定義的響應(yīng)式數(shù)據(jù)中的某個(gè)屬性時(shí),且該屬性是一個(gè)對象,那么此時(shí)deep配置生效。
具體的watch函數(shù)的用法在下面代碼中都有所體現(xiàn),注釋詳細(xì)
<template> <div> <h2>當(dāng)前求和為:{{sum}}</h2> <button @click="sum++">點(diǎn)我+1</button> <hr> <h2>當(dāng)前的信息為:{{msg}} </h2> <!-- 點(diǎn)擊button拼接! --> <button @click="msg+='!'">修改數(shù)據(jù)</button> <hr> <h2>姓名:{{person.name}}</h2> <h2>年齡:{{person.age}}</h2> <h2>薪資:{{person.job.j1.salary}}</h2> <button @click="person.name+='~'"> 修改姓名</button> <button @click="person.age++"> 增長年齡</button> <button @click="person.job.j1.salary++"> 增長薪資</button> </div> </template> <script> import {ref,reactive,watch,watchEffect} from 'vue' export default { name:'demo', setup(){ //數(shù)據(jù) let sum = ref(0) let msg = ref('hello') let person = reactive({ name:'zhangsan', age:'18', job:{ j1:{ salary:20 } } }) //監(jiān)視(三個(gè)參數(shù),第一個(gè)是監(jiān)視的對象,第二個(gè)是監(jiān)視的回調(diào)函數(shù),第三個(gè)是監(jiān)視的配置) //情況一:監(jiān)視r(shí)ef所定義的一個(gè)響應(yīng)式數(shù)據(jù) watch(sum,(newValue,oldValue)=>{ console.log('sum的值變化了',newValue,oldValue) },{immediate:true,deep:true}) //immediate的值為true時(shí)表示非惰性的立即執(zhí)行的(默認(rèn)情況下是false) //deep深層次觸發(fā)(此處設(shè)置deep無意義) //情況二:監(jiān)視r(shí)ef所定義的多個(gè)響應(yīng)式數(shù)據(jù),寫成數(shù)組的形式 watch([sum,msg],(newValue,oldValue)=>{ console.log('sum或者msg變了',newValue,oldValue) }) //情況三:監(jiān)視r(shí)eactive所定義的響應(yīng)式數(shù)據(jù) //若監(jiān)視的是reactive定義的響應(yīng)式數(shù)據(jù),則無法正確獲得oldValue //若監(jiān)視的是reactive定義的響應(yīng)式數(shù)據(jù),則watch會強(qiáng)制開啟深度監(jiān)視 //我們發(fā)現(xiàn)改變person的任意一個(gè)屬性都會被監(jiān)視到 watch(person,(newValue,oldValue)=>{ console.log('person改變了',newValue,oldValue) }) //我們嘗試設(shè)置deep:false,關(guān)閉深度監(jiān)聽(目的:改變job的值不會被watch監(jiān)聽到) //但是我們發(fā)現(xiàn)deep:false并沒有生效,原因是此時(shí)watch監(jiān)視的是reactive定義的響應(yīng)式對象,默認(rèn)強(qiáng)制開啟了深度監(jiān)聽 watch(person,(newValue,oldValue)=>{ console.log('person改變了',newValue,oldValue) },{deep:false}) //情況四:監(jiān)視r(shí)eactive所定義的響應(yīng)式數(shù)據(jù)中的某個(gè)屬性 watch(()=>person.name,(newValue,oldValue)=>{ console.log('person的job改變了',newValue,oldValue) }) watch(()=>person.age,(newValue,oldValue)=>{ console.log('person的job改變了',newValue,oldValue) }) watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job改變了',newValue,oldValue) }) //從上邊我們發(fā)現(xiàn)改變name,age都會觸發(fā)監(jiān)聽,但是改變job不會 //這是因?yàn)閚ame和age屬性的值只是一個(gè)簡單的基本類型數(shù)據(jù), //而job屬性的值是一個(gè)對象,比較深,想要監(jiān)視到,就要開啟深度監(jiān)視,程序如下: watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job改變了',newValue,oldValue) },{deep:true})//此時(shí)job改變,會被監(jiān)視到,此處的deep配置生效 //需要和情況三進(jìn)行區(qū)分,此處watch監(jiān)視的是reactive所定義的對象中的某個(gè)屬性,而情況三watch監(jiān)視的是reactive所定義的對象 //情況五:監(jiān)視r(shí)eactive所定義的響應(yīng)式數(shù)據(jù)中的某些屬性,寫成數(shù)組的形式 watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{ console.log('person的name或age改變了',newValue,oldValue) }) //返回一個(gè)對象(常用) return{ sum, msg, person } } } </script>
watch取消監(jiān)聽
const stop1 = watch( [() => nameObj.name, () => nameObj.name], ([curName, curEng], [prevName, curEng]) => { console.log(curName, curEng, "----", prevName, curEng); setTimeout(() => { stop(); }, 5000); } );
深度解析watchEffect函數(shù)
函數(shù)用法如下代碼所示,注釋詳細(xì):
<template> <div> <h2>當(dāng)前求和為:{{sum}}</h2> <button @click="sum++">點(diǎn)我+1</button> <hr> <h2>當(dāng)前的信息為:{{msg}} </h2> <!-- 點(diǎn)擊button拼接! --> <button @click="msg+='!'">修改數(shù)據(jù)</button> <hr> <h2>姓名:{{person.name}}</h2> <h2>年齡:{{person.age}}</h2> <h2>薪資:{{person.job.j1.salary}}</h2> <button @click="person.name+='~'"> 修改姓名</button> <button @click="person.age++"> 增長年齡</button> <button @click="person.job.j1.salary++"> 增長薪資</button> </div> </template> <script> import {ref,reactive,watch,watchEffect} from 'vue' export default { name:'demo', setup(){ //數(shù)據(jù) let sum = ref(0) let msg = ref('hello') let person = reactive({ name:'zhangsan', age:'18', job:{ j1:{ salary:20 } } }) //watchEffect函數(shù)內(nèi)部所指定的回調(diào)中用到的數(shù)據(jù)只要發(fā)生變化,就會重新執(zhí)行回調(diào) //只有一個(gè)參數(shù),就是回調(diào) watchEffect(()=>{ const x1 = sum.value//因?yàn)閟um是ref定義的響應(yīng)式數(shù)據(jù),需要使用.value調(diào)用 const x2 = person.age console.log('watchEffect配置的回調(diào)執(zhí)行了') }) return{ sum, msg, person } } } </script>
watchEffect取消監(jiān)聽
const stop = watchEffect(() => { console.log(nameObj.name); setTimeout(() => { stop(); }, 5000); });
watchEffect與computed
watchEffect與computed有點(diǎn)像:
- 但是computed注重的計(jì)算出來的值(回調(diào)函數(shù)的返回值),所以必須要寫返回值。
- 而watchEffect更注重的是過程(回調(diào)函數(shù)的函數(shù)體),所以不用寫返回值。
- computed若是值沒有被使用時(shí)不會調(diào)用,但是watchEffect始終會調(diào)用一次
<template> <div> <h2>當(dāng)前求和為:{{sum}}</h2> <button @click="sum++">點(diǎn)我+1</button> <hr> <h2>當(dāng)前的信息為:{{msg}} </h2> <!-- 點(diǎn)擊button拼接! --> <button @click="msg+='!'">修改數(shù)據(jù)</button> <hr> <h2>姓名:{{person.name}}</h2> <h2>年齡:{{person.age}}</h2> <h2>薪資:{{person.job.j1.salary}}</h2> <button @click="person.name+='~'"> 修改姓名</button> <button @click="person.age++"> 增長年齡</button> <button @click="person.job.j1.salary++"> 增長薪資</button> </div> </template> <script> import {ref,reactive,watch,watchEffect, computed} from 'vue' export default { name:'demo', setup(){ //數(shù)據(jù) let sum = ref(0) let msg = ref('hello') let person = reactive({ name:'zhangsan', age:'18', job:{ j1:{ salary:20 } } }) let person1 = reactive({ firstName:'張', lastName:'三' }) //computed //計(jì)算屬性——簡寫(沒有考慮計(jì)算屬性被修改的情況) person1.fullName = computed(()=>{ //必須含有返回值 return person1.firstName+'-'+person1.lastName }) //計(jì)算屬性——完整寫法(考慮讀和寫) person1.fullName = computed({ //必須含有返回值 get(){ return person1.firstName+'-'+person1.lastName }, set(value){ const nameArr = value.split('-') person1.firstName = nameArr[0] person1.lastName = nameArr[1] } }) //watchEffect //可以不寫給返回值 watchEffect(()=>{ const x1 = sum.value//因?yàn)閟um是ref定義的響應(yīng)式數(shù)據(jù),需要使用.value調(diào)用 const x2 = person.age console.log('watchEffect配置的回調(diào)執(zhí)行了') }) return{ sum, msg, person, person1 } } } </script>
到此這篇關(guān)于Vue中watch與watchEffect的區(qū)別詳細(xì)解讀的文章就介紹到這了,更多相關(guān)watch與watchEffect的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue3?Watch踩坑實(shí)戰(zhàn)之watch監(jiān)聽無效
Vue.js中的watch選項(xiàng)用于監(jiān)聽Vue實(shí)例上某個(gè)特定的數(shù)據(jù)變化,下面這篇文章主要給大家介紹了關(guān)于Vue3?Watch踩坑實(shí)戰(zhàn)之watch監(jiān)聽無效的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05vue調(diào)用本地?cái)z像頭實(shí)現(xiàn)拍照功能
這篇文章主要介紹了vue調(diào)用本地?cái)z像頭實(shí)現(xiàn)拍照功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Vue中使用elementui與Sortable.js實(shí)現(xiàn)列表拖動(dòng)排序
這篇文章主要為大家詳細(xì)介紹了Vue中使用elementui與Sortable.js實(shí)現(xiàn)列表拖動(dòng)排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue項(xiàng)目使用md5加密、crypto-js加密、國密sm3及國密sm4的方法
密碼或者其他比較重要東西假如使用明文傳輸中是很危險(xiǎn)的,所以就需要前端一些加密協(xié)議,對密碼、手機(jī)號、身份證號等信息進(jìn)行保護(hù),下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目中使用md5加密、crypto-js加密、國密sm3及國密sm4的相關(guān)資料,需要的朋友可以參考下2022-12-12在vue中使用echarts(折線圖的demo,markline用法)
這篇文章主要介紹了在vue中使用echarts(折線圖的demo,markline用法),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07vue實(shí)現(xiàn)在線學(xué)生錄入系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)在線學(xué)生錄入系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05vue3使用threejs實(shí)現(xiàn)3D卡片水平旋轉(zhuǎn)效果的示例代碼
這篇文章主要介紹了在vue3中使用threejs實(shí)現(xiàn)3D卡片水平旋轉(zhuǎn)效果,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-04-04