前言:
前天我們學了 ref 和 reactive ,提到了響應式資料和 Proxy ,那我們今天就來了解一下,vue3 的響應式
在瞭解之前,先複習一下之前 vue2 的響應式原理
vue2 的響應式:
原理:
物件型別:透過 Object.defineProperty() 物件的讀取,修改進行攔截,也就是資料劫持,響應式的根基
缺點:因為只有 讀取和修改(get,set)所以新增屬性,和刪除屬性,頁面是不會重新整理的
陣列型別:透過重寫,更新陣列的一系列方法來實現攔截,假如你調了一個陣列的 push 方法,其實 push 是被二次重寫封裝的(對陣列的變更方法進行了重寫)
缺點:直接透過下標修改陣列,頁面不會更新
解決方法:用 this.$set(資料,新增名字,新增內容),this.$delete(資料,刪除的資料名)
vue3 的響應式:
透過 Proxy 代理 :攔截物件中任意屬性的變化,包括增,刪,改,查
透過 Reflect 反射 : 對被代理物件(源物件)的屬性進行操作
new Proxy(data,{
//攔截讀取的屬性值
get(target,prop){
return Reflect.get(targert,prop)
}
//攔截設定和新增
set(target,prop,value){
return Reflect.set(targert,prop,value)
}
// 攔截刪除
deleteProperty(target,prop){
return Reflect.deleteProperty(targert,prop)
}
})
這差不多就是 vue3 響應式的簡單原理,Proxy 比較之前的 Object.defineProperty 功能更詳細,和強壯
reactive 與 ref 的區別:
定義:
ref:用來定義基本資料型別
reactive:用來定義物件(陣列)型別資料
ps:ref 也可以用來定義物件(或陣列)型別資料,內部求助了 reactive
原理:
ref: 透過 Object.defineProperty()的 get 與 set 來實現響應式也就是資料劫持
reactive:透過使用 Proxy 來實現響應式,並用 Reflect 操作源物件內部資料
使用:
ref:用 ref 定義的資料,操作需要 .value
reactive ; 定義的資料,操作不需要
setup 的注意:
setup 的執行時機是在 beforeCreate 之前執行,this 是 undefined
setup的引數
props :值為物件,包含:元件外部傳遞過來,並且元件內部宣告接收了的屬性
context:上下文物件,有三個值分別是 attrs,slots,emit
attrs :物件,沒有在 props 宣告配置的屬性,相當於 vue2 的 this.$attrs
slots :插槽,相當於 this. $slots
emit :分發自定義事件的函式,相當於 this.$emit
計算屬性,computed函式
與 vue2 中的 computed 配置功能一致
watch 函式監聽:
與 vue2 中的 watch 配置功能一致
watch 監視 ref 基本資料:
情況一 :監視 ref 定義的一個響應式資料
let sum = ref(0)
watch(sum,(newValue,oldValue)=>{
console.log('監聽sum變了',newValue,oldValue)
})
情況二:監視 ref 定義的多個響應式資料
let msg = ref('你好啊')
let sum = ref(0)
watch([sum,msg],(newValue,oldValue)=>{
console.log('監聽sum變了',newValue,oldValue)
},{immediate:true})
ps:watch 一共可以傳遞三個值,第一個 監視的資料,監視的行為,watch 的配置
watch 監視 reactive 物件:
情況三:監視 reactive 所定義資料中的全部屬性
let preson = reactive({
name:'六扇老師',
age:18
})
watch(preson,(newValue,oldValue)=>{
console.log('監聽preson變了',newValue,oldValue)
},{deep:false}) // 此處的 deep 配置無效
ps:此處無法正確的獲得 oldValue,是 reactive 的問題無法解決
強制開啟深度監視(deep配置無效)
情況四:監視 reactive 所定義資料中的某一個屬性
watch(()=>preson.name,(newValue,oldValue)=>{
console.log('監聽preson.name變了',newValue,oldValue)
})
情況五:監視 reactive 所定義資料中的某些屬性
watch([()=>preson.name,()=>preson.age],(newValue,oldValue)=>{
console.log('監聽preson.name/preson.age變了',newValue,oldValue)
})
特殊情況:
let preson = reactive({
name:'六扇老師',
age:18,
job:{
j1:{ salary:30 }
}
})
watch(()=>preson.job,(newValue,oldValue)=>{
console.log('監聽preson.job變了',newValue,oldValue)
},{deep:true})
ps:如果單獨監視 reactive 物件裡面的物件的資料,則必須開啟 deep:true 深度監視,否則監視無效
watchEffect 函式:
watchEffect 函式是 vue3 新增的一個函式
和 watch 區別:
watch:既要指明監視屬性,也要指明監視的回撥
watchEffect :不用指明監視屬性,監視的回撥中使用了那個屬性,就預設監視那幾個屬性
watchEffect 和 computed 有點相識
不一樣的是,computed 注重計算出來的值,回撥函式的返回值,所以必須要寫返回值
watchEffect 更注重過程,回撥函式的函式體,所以不用寫返回值
let sum = ref(0)
let preson = reactive({
name:'六扇老師',
age:18,
job:{
j1:{ salary:30 }
}
})
// watchEffect vue3 新增
// 預設開啟 immediate,也有 deep
watchEffect(()=>{
const x1 = sum.value const
x2 = preson.job.j1.salary
console.log('所指定的 watchEffect 的回撥執行了')
})
這就是今天的全部內容,我們明天見!這裡是六扇有伊人