概述
上节详细 说明ref、reactive如何定义使用响应式数据。总结如下:
- ref定义基础类型数据
- reactive定义对象数据
- 但ref也可以定义对象类型的数据。但底层基于reactive实现 ref定义对象类型数据,底层用reactive实现, 但两者区别在何处,本文将详细说明
ref使用对象类型的数据定义响应式
- 新建组件Fish
- 创建响应式对象fish,数组fishs
- 显示、修改响应式对象fish数据、fishs第一条数据
xml
<template>
<h2>鱼类:{{ fish.name }}</h2>
<h2>价格:{{fish.price }}</h2>
<button @click="changeName">改变鱼</button>
<button @click="addPrice">涨价</button>
<h3>鱼的列表</h3>
<ul>
<li v-for="item in fishs" :key="item.id">
{{ item.name }}:{{ item.price }}
</li>
</ul>
<button @click="changeFirstPrice">改变第三条鱼的价格</button>
</template>
<script setup>
import { ref } from 'vue'
let fish = ref({ name: '鲫鱼', price: 10 });
let fishs = ref([
{id:'txdi01',name:'鲫鱼',price:10},
{id:'txdi02',name:'鲤鱼',price:20},
{id:'txdi03',name:'草鱼',price:30},
])
function changeName() {
fish.value.name = '草鱼';
console.log(fish);
console.log(fish.value);
}
function addPrice() {
fish.value.price += 10;
}
function changeFirstPrice() {
fishs.value[0].price += 10;
}
</script>
用ref定义的响应式对象,需要用.value去访问赋值。访问页面,发现他与reactive定义的响应式对象是一样的,除了reactive不需要用.value访问。如图
在点击按钮改变鱼,打印输入fish和fish.value,发现fish使用RefImpl定义,但 fish.value使用Proxy定义的对象,这与使用reactive定义是一样的。使用ref定义的响应式对象,底层使用reactive实现的。
ref对比reactive区别
从使用整体看
- ref定义可以是基础数据、对象类型数据
- reactive定义只能是对象类型数据
从细微之处看两者区别
- ref创建的响应式对象,必须使用.value
- reactive是深层次响应对象
- reactive重新分配一个新对象,会丢失响应式
ref与reactive实际项目使用原则
- 基本类型数据,必须使用ref
- 简单的对象,不需要层级太深,ref、reactive都可以
- 层级较深的对象,推荐使用reactive 以上使用原则,简单归纳,基本数据使用ref、对象使用reactive。但实际要清楚两者在深层次对象使用区别。
如何正确理解reactive重新分配一个新对象会流失响应式
reactive重新分配一个新对象会流失响应式是官方的说明。猛一看有些懵。我们从事例代码中去理解这句话的含义。事例中,定义let fish = reactive({ name: '鲫鱼', price: 10 }),创建5个按钮
- 改变鱼的种类,fish.name = '草鱼';
- 改变鱼的价格,fish.price += 10;
- 方式一改变整个鱼,fish={ name: '鲤鱼', price: 30 }
- 方式二改变整个鱼,fish = reactive({ name: '鲤鱼鱼', price: 40 });
- 方式三改变整个鱼,Object.assign(fish,{ name: '带鱼', price: 50 }) 运行查看效果,发现,点击按钮方式一改变整个鱼、方式二改变整个鱼,页面无任何变。方式一、方式二都是重新给fis分配一个新的对象,导致fish丢失响应式。方式三是将新对象数据重新分配给fish,所以可以。 当fish丢失响应式数据后,再给fish重新赋值,页面也无法改变,也不在具有响应式。 细看图中的操作:

详细代码
xml
<template>
<h2>鱼类:{{ fish.name }}</h2>
<h2>价格:{{fish.price }}</h2>
<button @click="changeName">改变鱼的种类</button>
<button @click="addPrice">改变鱼的价格</button>
<div>
<button @click="changeallfish1">方式一改变整个鱼</button>
<button @click="changeallfish2">方式二改变整个鱼</button>
<button @click="changeallfish3">方式三改变整个鱼</button>
</div>
</template>
<script setup>
import { reactive } from 'vue'
let fish = reactive({ name: '鲫鱼', price: 10 });
function changeName() {
fish.name = '草鱼';
}
function addPrice() {
fish.price += 10;
}
function changeallfish1() {
fish={ name: '鲤鱼', price: 30 }
}
function changeallfish2() {
fish = reactive({ name: '鲤鱼鱼', price: 40 });
}
function changeallfish3() {
console.log('sadsd')
Object.assign(fish, { name: '带鱼', price: 50 })
console.log(fish);
}
</script>
ref定义的响应式对象重新分配一个新对象会怎样
- 使用.value赋值,是响应式
- 直接赋值,流失响应式 看事例
xml
<template>
<h2>鱼类:{{ fish.name }}</h2>
<h2>价格:{{fish.price }}</h2>
<button @click="changeallfish1">方式一改变整个鱼</button>
<button @click="changeallfish2">方式二改变整个鱼</button>
</template>
<script setup>
import { ref } from 'vue'
let fish = ref({ name: '鲫鱼', price: 10 });
function changeallfish1() {
fish.value={ name: '鲤鱼', price: 30 }
}
function changeallfish2() {
fish = ref({ name: '鲤鱼鱼', price: 40 });
}
</script>
