【vue3】一文读懂ref与reactive
开发中如何选择使用ref和reactive呢?有时真不知道怎么选择
Ref
ref数据响应式监听。ref 函数传入一个值作为参数,一般传入基本数据类型,返回一个基于该值的响应式Ref对象,该对象中的值一旦被改变和访问,都会被跟踪到,就像我们改写后的示例代码一样,通过修改 count.value 的值,可以触发模板的重新渲染,显示最新的值
<template>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<button @click="sayName">测试</button>
</template>
<script lang="ts">
import {ref,computed} from 'vue'
export default {
name: 'App',
setup(){
const name = ref('daxiong')
const birthYear = ref(2000)
const now = ref(2020)
const age = computed(()=>{
return now.value - birthYear.value
})
const sayName = () =>{
name.value = 'I am ' + name.value
}
return {
name,
sayName,
age
}
}
}
</script>
ref
的作用就是将一个原始数据类型(primitive data type)转换成一个带有响应式特性
的数据类型,原始数据类型共有7个,分别是:
- String
- Number
- BigInt
- Boolean
- Symbol
- Null
- Undefined
reactive
reactive是用来定义更加复杂的数据类型,但是定义后里面的变量取出来就不在是响应式Ref对象数据了
所以需要用toRefs函数转化为响应式数据对象
<template>
<div>
<h1>{{ name }}</h1>
<h1>{{ age }}</h1>
<button @click="sayName">测试</button>
</div>
</template>
<script lang="ts">
import { computed, reactive,toRefs } from "vue";
interface DataProps {
name: string;
now: number;
birthYear: number;
age: number;
sayName: () => void;
}
export default {
name: "App",
setup() {
const data: DataProps = reactive({
name: "daxiong",
birthYear: 2000,
now: 2020,
sayName: () => {
console.log(data.name);
data.name = "I am " + data.name;
console.log(data.name);
},
age: computed(() => {
return data.now - data.birthYear;
}),
});
return {
...refData,
};
},
};
</script>
Bug
不出意外,你会发现这个简化后的代码竟然无效,不管怎么点按钮,页面并没有发生变化!事实上,这样写没有效果的原因就在于一个响应型对象(reactive object) 一旦被销毁或展开(如上面代码那样),其响应式特性(reactivity)就会丢失。
toRefs的作用
为了解决上述问题,Vue3又提供了一个新的API:toRefs,它可以将一个响应型对象(reactive object) 转化为普通对象(plain object),同时又把该对象中的每一个属性转化成对应的响应式属性(ref)。说白了就是放弃该对象(Object)本身的响应式特性(reactivity),转而给对象里的属性赋予响应式特性(reactivity)。故而我们可以将代`码修复成下面这样:
<template>
<div>
<h1>{{ name }}</h1>
<h1>{{ age }}</h1>
<button @click="sayName">测试</button>
</div>
</template>
<script lang="ts">
import { computed, reactive,toRefs } from "vue";
interface DataProps {
name: string;
now: number;
birthYear: number;
age: number;
sayName: () => void;
}
export default {
name: "App",
setup() {
const data: DataProps = reactive({
name: "daxiong",
birthYear: 2000,
now: 2020,
sayName: () => {
console.log(data.name);
data.name = "I am " + data.name;
console.log(data.name);
},
age: computed(() => {
return data.now - data.birthYear;
}),
});
const refData = toRefs(data)
return {
...refData,
};
},
};
</script>
总结
ref 和 reactive 一个针对原始数据类型,而另一个用于对象,这两个API都是为了给JavaScript普通的数据类型赋予响应式特性(reactivity)。根据Vue3官方文档,这两者的主要区别在于每个人写JavaScript时的风格不同,有人喜欢用原始数据类型(primitives),把变量单独拎出来写;而有人喜欢用对象(Object),把变量当作对象里的属性,都写在一个对象里头,比如:
// style 1: separate variables
let x = 0
let y = 0
function updatePosition(e) {
x = e.pageX
y = e.pageY
}
// --- compared to ---
// style 2: single object
const pos = {
x: 0,
y: 0
}
function updatePosition(e) {
pos.x = e.pageX
pos.y = e.pageY
}
学习交流群:211042548