Vue3 的ref和reactive的用法和区别

一、是什么?

ref和reactive是Vue3中用来实现数据响应式的API,一般情况下,ref定义基本数据类型,reactive定义引用数据类型

二、基础用法

1. ref

ref的参数一般是基本数据类型,也可以是对象类型;如果参数是对象类型,其实底层的本质还是reactive,系统就会自动将ref转换为reactive;我们如果去访问ref定义的值,那么就使用.value的属性去访问定义的数据;ref的底层原理同reactive一样,都是Proxy。

基础用法

let num = ref(0) // 定义
let isShow = ref(false)  // 定义

const onChange = () => {
	num.value++  // js使用
	isShow.value = true  // js使用
}
<!-- Vue3模板引用使用 -->
<Modal v-model="isShow"></Modal>

2. reactive

reactive定义引用数据类型(以对象和数组举例),它能够将复杂数据类型的内部属性或者数据项声明为响应式数据,所以reactive的响应式是深层次的,其底层是通过ES6的Proxy来实现数据响应式,相对于Vue2的Object.defineProperty,具有能监听增删操作,能监听对象属性的变化等优点。

基础用法

const pageConfig = reactive({
	pageNum: 1,
	pageSize: 10
}) // 定义

const onChange = () => {
	pageConfig.pageNum = 2;
	pageConfig.pageSize = 20;
}
<!-- Vue3模板引用使用 -->
<Page :current="pageConfig.pageNum"></Page>

若用reactive定义基本数据类型,Vue3会报警告错误,如图

const str = reactive('字符串')

 3. ref和reactive定义数组对比

ref定义数组

const tableData = ref([]) // 定义

const getTableData = async () => {
	const { data } = await getTableDataApi() // 模拟接口获取表格数据
	tableData.value = data // 修改
}
<!-- Vue3模板引用使用 -->
<Table :data="tableData"></Table>

以我们常用的表格数据举例,可以看到,ref定义数组与定义基本数据类型没什么差别,接下来看看reactive

const tableData = reactive([]) // 定义

const getTableData = async () => {
	const { data } = await getTableDataApi() // 模拟接口获取表格数据
	tableData = data // 修改,错误示例,这样赋值会使tableData失去响应式
}
<!-- Vue3模板引用使用 -->
<Table :data="tableData"></Table>

需要注意的是,reactive定义的数组使用 tableData = data 的修改方式会造成 tableData 响应式丢失,解决方法如下:

// 方法一:改为 ref 定义
const tableData = ref([])
const getTableData = async () => {
	const { data } = await getTableDataApi()
	tableData.value = data // 使用.value重新赋值
}
// 方法二:使用 push 方法
const tableData = reactive([])
const getTableData = async () => {
	const { data } = await getTableDataApi()
	tableData.push(...data) // 先使用...将data解构,再使用push方法
}
// 方法三:定义时数组外层嵌套一个对象
const tableData = reactive({ list:[] })
const getTableData = async () => {
	const { data } = await getTableDataApi()
	tableData.list = data // 通过访问list属性重新赋值
}

4. Proxy vs defineProperty

reactive方法内部是利用ES6的Proxy API来实现的,这里与Vue2中的defineProperty方法有本质的区别。

  • defineProperty只能单一地监听已有属性的修改或者变化,无法检测到对象属性的新增或删除,而Proxy可以轻松实现;
  • defineProperty无法监听属性值是数组类型的变化,而Proxy可以轻松实现。

三、ref 和reactive的区别

  • ref用于定义基本类型和引用类型,reactive仅用于定义引用类型;
  • reactive只能用于定义引用数据类型的原因在于内部是通过ES6的Proxy实现响应式的,而Proxy不适用于基本数据类型;
  • ref定义对象时,底层会通过reactive转换成具有深层次的响应式对象,所以ref本质上是reactive的再封装;
  • 在JS中我们如果去对数据进行操作,在ref定义的数据中,使用变量.value;访问reactive不需要;
  • 在定义数组时,建议使用ref,从而可避免reactive定义时值修改导致的响应式丢失问题。
     

猜你喜欢

转载自blog.csdn.net/weixin_42775304/article/details/132041099