vue3 第二天vue響應式原理以及ref和reactive區別

六扇有伊人 發表於 2022-11-28
Vue React

前言:

前天我們學了 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 

vue3 第二天vue響應式原理以及ref和reactive區別

計算屬性,computed函式

與 vue2 中的 computed 配置功能一致

vue3 第二天vue響應式原理以及ref和reactive區別

 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 的回撥執行了')

})

這就是今天的全部內容,我們明天見!這裡是六扇有伊人