Vue3 ref和reactive的使用和區(qū)別以及響應式原理

這里介紹下ref和reactive函數(shù)的使用區(qū)別和響應式原理,以及在實際項目中如何使用和一些常見問題

ref函數(shù):

語法:const xxx = ref (initValue)
接受的數(shù)據(jù)類型:基本類型,引用類型
作用:把參數(shù)加工成一個響應式對象,全稱為reference對象(我們下面一律簡稱為ref對象)
核心原理:如果使用的是基本類型響應式依賴Object.defineProperty( )的get( )和set( ),如果ref使用的是引用類型,底層ref會借助reactive的proxy 定義響應式
基本使用:

<template>
  <h3>{{ refBaseType }}</h3>
  <h3>{{ refReferenceType }}</h3>
</template>

<script setup>
import { ref } from 'vue'
let refBaseType = ref(null)
//ref 需要用.value去獲取值
refBaseType.value = 'i am ref'
console.log('refBaseType', refBaseType)
//打印結果
/*
RefImpl {_shallow: false, dep: undefined, __v_isRef: true, _rawValue: "i am ref", _value: "i am ref"}
dep: undefined
__v_isRef: true
_rawValue: "i am ref"
_shallow: false
_value: "i am ref"
value: "i am ref"
__proto__: Object
* */
//如果ref使用的是對象,底層ref會借助reactive的proxy ******
let refReferenceType = ref({})
refReferenceType.value = { count: 1 }
console.log('refReferenceType', refReferenceType)
//打印結果
/*
RefImpl {_shallow: false, dep: undefined, __v_isRef: true, _rawValue: {…}, _value: Proxy}
dep: Set(1) {ReactiveEffect}
__v_isRef: true
_rawValue: {count: 1}
_shallow: false
_value: Proxy {count: 1}
value: Proxy  //如果ref使用的是對象,底層ref會借助reactive的proxy
[[Handler]]: Object
[[Target]]: Object
[[IsRevoked]]: false

* */
</script>

<style lang="scss" scoped>

</style>

如果ref使用的是對象,ref會借助reactive生成proxy

reactive函數(shù):

語法:const xxx = ref (源對象)
接受的數(shù)據(jù)類型:引用類型
作用:把參數(shù)加工成一個代理對象,全稱為proxy對象
核心原理:基于Es6的Proxy實現(xiàn),通過Reflect反射代理操作源對象,相比于reactive定義的淺層次響應式數(shù)據(jù)對象,reactive定義的是更深層次的響應式數(shù)據(jù)對象

基本使用:

<template>
  <h3>{{ reactiveBaseType }}</h3>
  <h3>{{ reactiveReferenceType }}</h3>
  <div @click="setData">setData</div>
  <div @click="setReactive">setReactive</div>
</template>

<script setup>
import { reactive } from 'vue'
let reactiveBaseType = reactive(null)
//reactive 無法定義基本類型的proxy,且設置值無法響應數(shù)據(jù)
let setData = () => {
  reactiveBaseType = 'fai'
}
console.log('reactiveBaseType', reactiveBaseType)
//打印結果
/*
null
* */
//如果reactive使用的是引用類型
let reactiveReferenceType = reactive({ count: 1 })
let setReactive = () => {
  //這樣設置會去proxy
  reactiveReferenceType = { count: 1 }
  console.log(reactiveReferenceType)
  //打印結果
  /*
   *{count: 1} //proxy 沒了,所以reactive申明的無法直接替換整個對象,如果有這個需求請使用ref
   * */
}
console.log('reactiveReferenceType', reactiveReferenceType)
//打印結果
/*
//proxy響應式
Proxy {count: 1}
[[Handler]]: Object
[[Target]]: Object
count: 1
__proto__: Object
[[IsRevoked]]: false
* */
</script>

<style lang="scss" scoped>

</style>

注:reactive申明的無法直接替換整個對象,如果有這個需求請使用ref

總結:

ref和reactive都可以做響應式

ref:一般用在定義基本類型和引用類型,如果是引用類型底層會借助reactive形成proxy代理對象,可以直接復制整個對象,如table的數(shù)據(jù)請求回來,需要將數(shù)據(jù)整體賦值個響應對象這時如果使用的是reactive就無法進行響應。

reactive:一般用在引用類型,如{}等,不能一次性修改整個對象,如我們后端請求table的數(shù)據(jù)數(shù)據(jù),如果想一次性賦值的整個數(shù)組的話,就行不通,此時建議使用ref來定義數(shù)組。

ref和reactive建議使用

第一種寫法:除了對象都用ref來定義

let switchKG = ref(false)
console.log(switchKG.value)

let arr = ref([])
arr.value = [1, 2, 3, 4, 5]
console.log(arr.value)

let Obj = reactive({
  arr: []
})
reactive.arr = [1, 2, 3, 4, 5]

第二種寫法:都用reactive來定義,然后用toRefs進行導出到頁面使用

<template>
  <div>{{arr}}</div>
  <div>{{obj}}</div>
  <div>{{swithKW}}</div>
</template>
<script setup>
import {reactive, toRefs} from "vue";

let state = reactive({
  swithKW:false,
  arr: [],
  obj: {}
})
console.log(state.arr)
console.log(state.obj)
//導出到頁面使用
const {swithKW, arr, obj } = toRefs(state)
</script>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容