vue3中ref和reactive区别
ref
和reactive
是Vue3
中用来实现数据响应式的API,一般情况下,ref
定义基本数据类型,reactive
定义引用数据类型。
2.1 ref
- 理解:
ref
的参数一般是基本数据类型,也可以是对象类型;如果参数是对象类型,其实底层的本质还是reactive
,系统就会自动将ref
转换为reactive
;我们如果去访问ref
定义的值,那么就使用.value
的属性去访问定义的数据;ref
的底层原理同reactive
一样,都是Proxy
。 - 语法:
const xxx = ref(initValue)
基础用法
<template><h1>{{ name }}</h1> <button @click="changeName">修改名称</button></template><script setup>import { ref} from 'vue'const name = ref('张三')const changeName = () => {name.value = '李四'age.value = 20}</script>
2.2 reactive
reactive
定义引用数据类型(以对象和数组举例),它能够将复杂数据类型的内部属性或者数据项声明为响应式数据,所以reactive
的响应式是深层次的,其底层是通过ES6
的Proxy
来实现数据响应式,相对于Vue2
的Object.defineProperty
,具有能监听增删操作,能监听对象属性的变化等优点。
基础用法
<template><Child:current="pageConfig.pageNum"></Child></template><script setup>import { reactive} from 'vue'const queryParams= reactive({pageNum: 1,pageSize: 10}) const onChange = () => {queryParams.pageNum = 2;queryParams.pageSize = 20;}</script>
若用reactive
定义基本数据类型,Vue3
会报警告错误,如图
const str = reactive('字符串')
3.1 ref定义数组
<template><Table :data="tableData"></Table></template><script setup>import { ref, reactive, onMounted } from 'vue'import { getTableDataApi } from '@/api'const queryParams= reactive({pageNum: 1,pageSize: 10}) const tableData = ref([]) onMounted(() => {getTableData()})const getTableData = async () => {const { data } = await getTableDataApi(queryParams) // 模拟接口获取表格数据tableData.value = data }</script>
以我们常用的表格数据举例,可以看到,ref
定义数组与定义基本数据类型没什么差别,接下来看看reactive
3.1 reactive定义数组
<template><Table :data="tableData"></Table></template><script setup>import { ref, reactive, onMounted } from 'vue'import { getTableDataApi } from '@/api'const queryParams= reactive({pageNum: 1,pageSize: 10}) const tableData = reactive([]) onMounted(() => {getTableData()})const getTableData = async () => {const { data } = await getTableDataApi(queryParams) // 模拟接口获取表格数据tableData= data }</script>
需要注意的是,reactive
定义的数组使用 tableData = data
的修改方式会造成 tableData
响应式丢失。
解决方法如下:
// 方法一:改为 ref 定义const tableData = ref([])const getTableData = async () => {const { data } = await getTableDataApi(queryParams)tableData.value = data // 使用.value重新赋值}// 方法二:使用 push 方法const tableData = reactive([])const getTableData = async () => {const { data } = await getTableDataApi(queryParams)tableData.push(...data) // 先使用...将data解构,再使用push方法}// 方法三:定义时数组外层嵌套一个对象const tableData = reactive({ list:[] })const getTableData = async () => {const { data } = await getTableDataApi(queryParams)tableData.list = data // 通过访问list属性重新赋值}
- ref用于定义基本类型和引用类型,reactive仅用于定义引用类型;
- reactive只能用于定义引用数据类型的原因在于内部是通过ES6的Proxy实现响应式的,而Proxy不适用于基本数据类型;
- ref定义对象时,底层会通过reactive转换成具有深层次的响应式对象,所以ref本质上是reactive的再封装;
- 在JS中我们如果去对数据进行操作,在ref定义的数据中,使用变量.value;访问reactive不需要;
- 在定义数组时,建议使用ref,从而可避免reactive定义时值修改导致的响应式丢失问题。
来源地址:https://blog.csdn.net/DZQ1223/article/details/132448112