前言
在Vue2中的响应式数据需要放入 data 函数,Vue2 会遍历 data 中的所有属性,使用的Object.defineProperty 把每个 property 全部转为 getter/setter,getter 用来收集依赖,setter 用来执行 notify,发布更新事件。
而在Vue 3的响应式系统中使用了ref和reactive 这两个核心概念,它们为开发者提供了处理响应式数据的不同方式。理解它们的特性和区别对于构建灵活、高效的Vue应用至关重要。
ref
基本作用
ref的作用是将一个普通的 JavaScript 变量(该变量可以是基本类型的数据,也可以是引用类型的数据)包装成一个响应式的数据。
基本用法
1、首先,先看看 ref 函数传入的参数为原始数据类型(String, Number, Boolean, BigInt, Symbol, Null, Undefined)的情况:
- html部分
<template>
<div class="main">
<p>count: {{ count }}</p>
<button @click="countChange">count++</button>
</div>
</template>
- Javascript部分
import { ref } from 'vue';
// 使用 ref 声明一个变量
const count = ref(0);
const countChange = () => {
console.log(count.value); // 0
count.value++; // 变更变量的值
console.log(count.value); // 1
}
这里的count是一个带有value属性的对象,通过value来访问或修改变量的值。在模板中,Vue会自动解包ref,所以在模板html中直接使用变量即可,无需额外的value。
- setup()中使用
<template>
<div>{{ count }}</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const count = ref(0);
return { count };
},
};
</script>
//----setup语法-----
<script setup>
import { ref } from 'vue';
const count = ref(0); //无需return变量
</script>
<template>
<div>{{ count }}</div>
</template>
2、然后是引用数据
<script setup>
import { ref } from 'vue'
const people = ref({ age: 18 })
const changePeopleAge = () => {
people.value.age += 10
}
</script>
<template>
<div class="main">
<p>age: {{people.age}}</p>
<button @click="changePeopleAge ">修改个人年龄</button>
</div>
</template>。
从上面可以看出,ref可以传递原始数据也可以传递引用数据,同时传递对象类型的数据时,对象的属性存储在了value属性之下。
3、ref的数据解包
- 在模板渲染上下文中,只有顶级的 ref 属性才会被解包。
- 如果文本插值表达式( {{ }} )计算的最终值是 ref ,那么也会被自动解包。
<template>
<div class="main">
<p>count: {{ count + 1 }}(该写发会自动解包)</p>
<p>age: {{ person.age + 1 }}(该写法不会自动解包,渲染结果为age: [object Object]1)</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const person = {
age: ref(26)
}
</script>
为了解决这个问题,我们可以将 age 解构成为一个顶级属性:
<script setup>
import { ref } from 'vue'
const person = {
age: ref(26)
}
const { age } = person
</script>
<template>
<div class="main">
<p>age: {{ age + 1 }}</p>
</div>
</template>
使用场景
使用ref的主要原因在于其轻量且直观的特性。它适用于管理简单的变量,而且在模板中的使用非常自然。对于那些不需要复杂嵌套结构的数据,ref是一个高效、易懂的选择。在处理单一状态时,它是一个强大的工具。