前言: 前天我們學了 ref 和 reactive ,提到了響應式數據和 Proxy ,那我們今天就來瞭解一下,vue3 的響應式 在瞭解之前,先複習一下之前 vue2 的響應式原理 vue2 的響應式: 原理: 對象類型:通過 Object.defineProperty() 對象的讀取,修改進行攔 ...
前言:
前天我們學了 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 的回調執行了')
})
這就是今天的全部內容,我們明天見!這裡是六扇有伊人