所謂響應式就是界面和數(shù)據(jù)同步,能實現(xiàn)實時更新。
Vue 中用過三種響應式解決方案,分別是 defineProperty、Proxy 和 value setter。Vue 2 使用的方案是 defineProperty API。Vue3中使用的方案是Proxy和value setter。
1. ref和reactive
vue3中實現(xiàn)響應式數(shù)據(jù)的方法是使用ref和reactive。
reactive更推薦去定義復雜的數(shù)據(jù)類型,ref 更推薦定義基本類型。
通過reactive定義響應式數(shù)據(jù)。
<template>
<div>
<h1 @click="add">{{ obj.count }} * 2 = {{ double }}</h1>
</div>
</template>
<script setup>
import { computed, reactive, watchEffect } from 'vue';
let obj = reactive({ // reactive包括復雜數(shù)據(jù)類型,使其成為響應式數(shù)據(jù)。
count: 1
})
function add() { // 改變obj.count屬性。與ref的不同。
obj.count++
}
let double = computed(()=>obj.count*2) // double會自動跟隨obj.count變化
watchEffect(() => {
console.log("數(shù)據(jù)被修改了",obj.count,double.value) // 控制臺可以看到double數(shù)據(jù)變化了(通過double.value)。
})
</script>
通過ref定義響應式數(shù)據(jù)。修改數(shù)據(jù)要通過.value。
<template>
<div>
<h1 @click="add">{{ count }} * 2 = {{ double }}</h1>
</div>
</template>
<script setup>
import { computed, ref, watchEffect } from 'vue';
let count = ref(1) // ref包裹簡單數(shù)據(jù)類型,使其成為響應式數(shù)據(jù),修改數(shù)據(jù)要通過.value
function add() { // 改變count,通過count.value修改值(方式與reactive包裹的數(shù)據(jù)不同)
count.value++;
}
let double = computed(()=>count.value*2) // double會自動跟隨count變化
watchEffect(() => {
console.log("數(shù)據(jù)被修改了",count.value,double.value) // 控制臺可以看到double數(shù)據(jù)變化了
})
</script>
通過這兩個例子,對比了ref和reactive的區(qū)別。
watchEffect 這個函數(shù)讓我們在數(shù)據(jù)變化之后可以執(zhí)行指定的函數(shù)。
2. watchEffect舉個例子
使用 watchEffect,在數(shù)據(jù)變化之后,把數(shù)據(jù)同步到 localStorage 之上,實現(xiàn) todolist 和本地存儲的同步。修改 https://liuchunming.blog.csdn.net/article/details/130508826 第五小節(jié)的代碼,在function useTodos()中添加如下兩行的代碼。
...
let todos = ref(JSON.parse(localStorage.getItem('todos')||'[]'));
watchEffect(()=>{
localStorage.setItem('todos',JSON.stringify(todos.value))
})
...
效果:
添加待辦項后,todos這個響應式變量發(fā)生變化,watchEffect中的回調(diào)函數(shù)就會自動執(zhí)行,將todos添加到localstorge中。
當清理待辦項后,todos這個響應式變量也會發(fā)生變化,watchEffect中的回調(diào)函數(shù)就會自動執(zhí)行,將todos添加到localstorge中。
3. watch舉個例子
需求:在 loading 狀態(tài)下,去修改瀏覽器的小圖標 favicon。
通過watch監(jiān)聽favicon變化,修改href標簽屬性。
watch(WatcherSource, Callback, [WatchOptions]) 參數(shù):
WatcherSource:想要監(jiān)聽的響應式數(shù)據(jù)。
Callback:執(zhí)行的回調(diào)函數(shù),入?yún)ⅲ╪ewValue, oldValue)。
[WatchOptions]:deep、immediate、flush可選。
對于WatchOptions的參數(shù)配置:
deep:當需要對對象等引用類型數(shù)據(jù)進行深度監(jiān)聽時,設置deep: true,默認值是false。
immediate:默認情況下watch是惰性的,設置immediate: true時,watch會在初始化時立即執(zhí)行回調(diào)函數(shù)一次。
flush:控制回調(diào)函數(shù)的執(zhí)行時機,。它可設置為 pre、post 或 sync。
pre:默認值,當監(jiān)聽的值發(fā)生變更時,優(yōu)先執(zhí)行回調(diào)函數(shù)(在dom更新之前執(zhí)行)。
post:dom更新渲染完畢后,執(zhí)行回調(diào)函數(shù)。
sync:一旦監(jiān)聽的值發(fā)生了變化,同步執(zhí)行回調(diào)函數(shù)(建議少用)。
參考資料:https://blog.csdn.net/weixin_42349568/article/details/126760186
實現(xiàn)需求:
utils中新建一個favicon.js文件。我們把對圖標的對應修改的操作封裝成了 useFavicon 函數(shù),并且通過 ref 和 watch 的包裹,我們還把小圖標變成了響應式數(shù)據(jù)。
import { ref, watch } from "vue";
// 【知識點1】:變量和常量定義:
// let是ES6中新增的聲明變量的關鍵字。?let聲明的變量只在所處的塊級作用域有效,也就是所聲明的大括號內(nèi)。let定義的變量不存在變量提升。
// var 聲明變量,不具備這個塊級作用域的特性。在大括號外也可以訪問。使用var聲明變量的時候,其作用域在所在的函數(shù)內(nèi),而且存在變量提升。
// const關鍵字。ES6中除了新增的聲明常量的關鍵字,這里的常量就是值值不能變化的量。必須賦值否則就會報錯。具有塊級作用域,只在所處的塊級作用域有效,也就是所聲明的大括號內(nèi)。
// 【知識點2】:JS中的=>代表箭頭函數(shù)
// 當只有一個參數(shù)時,圓括號是可選的:(singleParam) => { statements } 可以寫成singleParam => {statements }
// 沒有參數(shù)的函數(shù)應該寫成一對圓括號:() => { statements }
// statements簡單的,也可以去掉大括號:el => el.href = `${icon}`
export default function useFavicon(newIcon) { //export default只能有一個
const favicon = ref(newIcon);
const updateIcon = (icon) => { //更新icon
document.head
.querySelectorAll(`link[rel*="icon"]`) //反引號``括起來的字符串叫模板字符串,里面可以放空格、換行符等,還可以放JS表達式${}
.forEach(el => el.href = `${icon}`)
}
const reset = () => favicon.value = '/vite.svg' //重置icon, 通過修改faivcon.value
watch(favicon, // 監(jiān)聽favicon變化
(i) => { // favicon變化后,執(zhí)行的回調(diào)函數(shù)
updateIcon(i);
}
)
return { favicon, reset };
}
在關于頁面,調(diào)用更換favicon的功能:文章來源:http://www.zghlxwxcb.cn/news/detail-437544.html
<template>
<h1>這是關于頁面</h1>
<button @click="loadding">更換圖標</button>
<button @click="reset">重置圖標</button>
</template>
<script setup>
import useFavicon from '../utils/favicon';
let {favicon, reset} = useFavicon();
function loadding(){
favicon.value = "/geek-favicon-32x32.webp"
}
</script>
點擊更換圖標,herf變成/geek-favicon-32x32.webp:
點擊重置圖標,herf變回/vite.svg文章來源地址http://www.zghlxwxcb.cn/news/detail-437544.html
4. watchEffect和watch區(qū)別
- watchEffect 不需要指定監(jiān)聽的屬性,他會自動的收集依賴, 只要我們回調(diào)中引用到了 響應式的屬性, 那么當這些屬性變更的時候,這個回調(diào)都會執(zhí)行,而 watch 只能監(jiān)聽指定的屬性而做出變更(v3開始可以同時指定多個)。
- 就是 watch 可以獲取到新值與舊值(更新前的值),而 watchEffect 是拿不到的。
- 是 watchEffect 如果存在的話,在組件初始化的時候就會執(zhí)行一次用以收集依賴(與computed同理),而后收集到的依賴發(fā)生變化,這個回調(diào)才會再次執(zhí)行,而 watch 不需要,因為他一開始就指定了依賴
到了這里,關于【Vue學習筆記5】Vue3中的響應式:ref和reactive、watchEffect和watch的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!