美文网首页
Vue3 ref和reactive的使用和区别以及响应式原理

Vue3 ref和reactive的使用和区别以及响应式原理

作者: jzfai | 来源:发表于2021-11-12 13:32 被阅读0次

    这里介绍下ref和reactive函数的使用区别和响应式原理,以及在实际项目中如何使用和一些常见问题

    ref函数:

    语法:const xxx = ref (initValue)
    接受的数据类型:基本类型,引用类型
    作用:把参数加工成一个响应式对象,全称为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函数:

    语法:const xxx = ref (源对象)
    接受的数据类型:引用类型
    作用:把参数加工成一个代理对象,全称为proxy对象
    核心原理:基于Es6的Proxy实现,通过Reflect反射代理操作源对象,相比于reactive定义的浅层次响应式数据对象,reactive定义的是更深层次的响应式数据对象

    基本使用:

    <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,且设置值无法响应数据
    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的数据请求回来,需要将数据整体赋值个响应对象这时如果使用的是reactive就无法进行响应。

    reactive:一般用在引用类型,如{}等,不能一次性修改整个对象,如我们后端请求table的数据数据,如果想一次性赋值的整个数组的话,就行不通,此时建议使用ref来定义数组。

    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>
    

    相关文章

      网友评论

          本文标题:Vue3 ref和reactive的使用和区别以及响应式原理

          本文链接:https://www.haomeiwen.com/subject/ioxozltx.html