响应式数据概述
在vue2那个年代,响应式数据是在data里面定义,只要把数据放在data里,然后在模版内引用,数据一变,模版就跟着显示,如下图代码:
<template>
<h2>我是一条{{ fish }}</h2>
<button @click="changeFish">改变鱼</button>
</template>
<script lang="ts">
export default {
name:'Fish',
data() {
return {
fish:'鲫鱼'
}
},
methods: {
changeFish() {
this.fish+='!'
}
}
}
</script>
点击按钮改变鱼。fish一变化,模版就跟着变化,这就是响应式数据。
vue3是如何定义响应式数据的
在vue3中,使用的是组合式 API (Composition API)语法,它没有data,数据和方式都定义在script标签里。在定义数据时,有两种方式给数据标记成响应式数据,分别是ref、reactive。
- ref给基本数据标记成响应式数据,如整数、浮点数、字符串
- reactive给对象标记成响应式数据,如对象、数组
- ref也可给对象标记响应式数据,但底层用reactive实现
用ref给基本数据标记成响应式对象
- 从vue引入ref,才可以使用ref函数
- 定义响应式变量,用ref赋值
- 获取、改变响应式数据变量的值,不能直接访问,需要加.value
- 模版中可直接引用变量
<template>
<h1>鱼类:{{ fish }}</h1>
<h2>价格:{{price }}</h2>
<button @click="changeName">改变鱼</button>
<button @click="addPrice">涨价</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let fish = ref('鲫鱼');
let price =ref(10);
function changeName() {
fish.value = '草鱼';
console.log(fish);
console.log(fish.value);
}
function addPrice() {
price.value += 10;
console.log(price)
console.log(price.value)
}
</script>
在浏览中访问http://localhost:5173/,查看效果
当点击按钮,鱼与价格都跟着改变。fish与price变成响应式数据,控制台打印 console.log(price)、 console.log(price.value),发现定义fish与price,并不是字符串与数字,而是用RefImpl 类型的定义的数据,fish基本结构如下:
能够访问的属性,只有vulue。在changeFIsh与addPrice函数中,通过fish.value和price.value赋值
借助vue DevTools 工具查看Fish组件的数据与方法
想要谁变成响应式数据,在数据外面包一层ref。不需要的,直接定义变量。
reactive定义对象类型的响应式数据
- 从vue引入reactive
- 定义响应式对象,用reactive包裹对象
- 访问、改变响应式对象,直接操作成员变量
- 模版直接使用响应式对象 分别定义两个响应式数据,一是用对象定义的响应式,一是用数组定义的响应式,来说明响应式对象如何使用。
let fish = reactive({ name: '鲫鱼', price: 10 });
let fishs = reactive([
{id:'txdi01',name:'鲫鱼',price:10},
{id:'txdi02',name:'鲤鱼',price:20},
{id:'txdi03',name:'草鱼',price:30},
])
改变鱼的名称与价格
function changeName() {
fish.name = '草鱼';
}
function addPrice() {
fish.price += 10;
}
改变fishs第二个鱼的价格
function changeThreePrice() {
fishs[1].price += 10;
}
具体代码如下:
template>
<h2>鱼类:{{ fish.name }}</h2>
<h2>价格:{{fish.price }}</h2>
<button @click="changeName">改变鱼</button>
<button @click="addPrice">涨价</button>
<h2>鱼的列表</h2>
<ul>
<li v-for="item in fishs" :key="item.id">
{{ item.name }}:{{ item.price }}
</li>
</ul>
<button @click="changeThreePrice">改变第三条鱼的价格</button>
</template>
<script setup>
import { reactive } from 'vue'
let fish = reactive({ name: '鲫鱼', price: 10 });
let fishs = reactive([
{id:'txdi01',name:'鲫鱼',price:10},
{id:'txdi02',name:'鲤鱼',price:20},
{id:'txdi03',name:'草鱼',price:30},
])
function changeName() {
fish.name = '草鱼';
console.log(fish);
console.log(fish.name);
}
function addPrice() {
fish.price += 10;
}
function changeThreePrice() {
fishs[1].price += 10;
}
</script>
在浏览器访问http://localhost:5173/,数据渲染和修改都正确,如下图
通过reactive定义的数据,都是Proxy,这是JavaScript内置对象,它的数据存放在Target中。其结构如下图:
reactive定义的响应式对象是深层次
对象的深层次,是其成员变量中含有成员变量,其成员变量又含有成员变量,当修改最底层成员变量值时,数据也是响应式的。如下:
<template>
<h2>鱼类:{{ a.b.c.color }}</h2>
<button @click="changeC">深度改变</button>
</template>
<script setup>
import { reactive } from 'vue'
let a = reactive({
b: {
c: {
color: 'red'
}
}
})
a.b.c.color='black'
function changeC() {
a.b.c.color = 'black';
}
</script>
访问浏览器,点击深度改变按钮,发现color值是响应式。用reactive定义的响应式对象都是深层次的。