ref和reactive的使用

227 阅读3分钟

reactive API的使用

reactive方法用来创建响应式对象,它接收一个对象/数组参数,返回对象的响应式副本,当该对象的属性值发生变化,会自动更新使用该对象的方法。

接下来我们用对象数组来作为参数演示:

import {reactive, toRefs} from 'vue'
export default {
  setup() {
    const dataMap = reactive({
      reactiveName : 'Chris1993',
      reactiveArr : ['a','b','c','d']
    })
    const methodsMap = reactive({
      setReactiveObj : () => {
        dataMap.reactiveName = 'Hello Chris1993'
      },
      setReactiveArr: () => {
        dataMap.reactiveArr[1] = 'Hello Chris1993'
      }
    })
    return {
      ...toRefs(dataMap),
      ...toRefs(methodsMap)
    }
  }
}

模板如下:

  <h2>Vue3 reactive API Base</h2>
  <div>
      Object:{{reactiveName}}
      <span @click="setReactiveObj" class="button1">Update</span>
  </div>
  <div>
    Array:{{reactiveArr}}
    <span @click="setReactiveArr" class="button1">Update</span>
  </div>

此时页面如下:

image.png

当点击Update按钮后,数据会发生变化,同时视图上的内容会跟着一起更新:

image.png

ref API的使用

ref的作用就是将一个原始数据类型转换成一个带有响应式特性的数据类型,原始数据类型共有7个值,分别是StringBigInt,Number,Boolean,Symbol,Null,Undefined

ref的值在JS/TS中读取或修改时,需要使用 .value 来获取,而在模板中读取是不需要使用 .value

下面分别以字符串对象作为参数演示:

import {ref} from 'vue'
export default {
    setup() {
        let refValue = ref('Chris1993')
        let refObj = ref ({ name: 'Chris1993'})
        let setRefValue = () => {
            refValue.value = 'Hello Chris1993'
        }
        let setRefObj = () => {
            refObj.value.name = 'Hello Chris1993'
        }

        return {
            refValue,
            refObj,
            setRefValue,
            setRefObj
        }
    }
}

模板内容如下:

  <h2>Vue3 ref API Base</h2>
  <div>
      String: {{refValue}}
      <span @click="setRefValue" class="button">Update</span>
  </div>
  <div>
      Object: {{refObj.name}}
      <span @click="setRefObj" class="button">Update</span>
      <span></span>
  </div>

此时页面展示如下:

image.png

当我们分别点击Update按钮后,数据发生变化后,视图内容也一起更新了:

image.png

reactive可以用在深层对象或数组

reactive是基于ES2015 Proxy API实现的,它的响应式是整个对象的所有嵌套层级。

接下来用对象数组作为参数进行展示

import {reactive} from 'vue'
export default {
    setup() {
        let reactiveDeepObj = reactive({
            user:{name: 'Chris1993'}
        })
        let setReactiveDeepObj = () => {
            reactiveDeepObj.user.name = 'Hello Chris1993'
        }

        let reactiveDeepArr = reactive(['a',['a1','a2','a3'],'c','d'])
        let setReactiveDeepArr = () => {
            reactiveDeepArr[1][1] = 'Hello Chris1993'
        }

        return {
            reactiveDeepObj,
            reactiveDeepArr,
            setReactiveDeepObj,
            setReactiveDeepArr
        }
    }
}

模板内容如下:

  <h2>Vue3 reactive deep API Base</h2>
  <div>
      Object: {{reactiveDeepObj.user.name}}
      <span @click="setReactiveDeepObj" class="button">Update</span>
  </div>
  <div>
      Array: {{reactiveDeepArr}}
      <span @click="setReactiveDeepArr" class="button">Update</span>
  </div>

此时的页面如下:

image.png

当点击Update按钮后,数据产生变化后,视图内容也跟着一起更新:

image.png

reactive返回值和源对象不一样

reactive是基于ES2015 Proxy API实现的,返回结果是个proxy对象。

测试代码:

import {reactive} from 'vue'
import { onMounted } from '@vue/runtime-core'
export default {
    setup() {
        let reactiveSource = {name: 'Chris1993'}
        let reactiveData = reactive(reactiveSource)

        onMounted(() => {
            console.log(reactiveSource === reactiveData);
            console.log(reactiveSource);
            console.log(reactiveData);
        })
    }
    
}

输出如下:

image.png

把ref值作为reactive参数

当我们已有一个ref对象,需要使用在reactive对象中,会发生什么?

        let name = ref('Chris1993')
        let nameReactive = reactive({name})
        console.log(name.value === nameReactive.name);  //true

        name.value = 'Hi Chris1993'
        console.log(name.value); //Hi Chris1993
        console.log(nameReactive.name); //Hi Chris1993

        nameReactive.name = 'Hi Chris1993'        
        console.log(name.value); //Hi Chris1993
        console.log(nameReactive.name); //Hi Chris1993

reactive会将深层的refs进行解包,并且保持ref的响应式。

当通过赋值方式将ref分配给reactive属性时,ref也会自动被解包

        let name = ref('Chirs1993')
        let nameReactive = reactive({})
        nameReactive.name = name

        console.log(name.value); // Chris1993
        console.log(nameReactive.name); // Chris1993
        console.log(name.value === nameReactive.name); //true

总结

  1. reactive一般用于对象/数组类型的数据,都不需要使用 .value
  2. ref一般用于基础数据类型的数据,在JS中读取和修改时,需要使用 .value,在模板中使用时则不需要
  3. reactive可以修改深层属性值,并保持响应
  4. reactive返回值和源对象不同
  5. reactive的属性值可以是ref
  6. ref本质也是reactiveref(obj) 等价于 reactive({value: obj})