ref是Vue3提供的一种用于包装基本数据类型的响应式对象的实现方式。在Vue3中,使用ref可以将基本数据类型(如字符串、数字、布尔值等)包装为响应式对象。当这些基本数据类型的值发生变化时,Vue3会自动更新视图中相应的内容。
下面是一个使用ref的示例:
<template>
<div>
<p>{{ message }}p>
<button @click="updateMessage">更新button>
div>
template>
<script>
import { ref } from 'vue';
export default {
setup() {
const message = ref('Hello, World!');
const updateMessage = () => {
message.value = 'Hello, Vue3!';
};
return {
message,
updateMessage
};
}
};
script>
在这个例子中,我们使用了ref来包装一个字符串类型的数据。在setup函数中,我们将ref返回的响应式对象作为组件实例的一个属性,同时也将updateMessage函数返回给模板。当updateMessage函数被调用时,message的值会被更新为’Hello, Vue3!',并且视图中显示的内容也会被更新。
需要注意的是,在使用ref包装基本数据类型时,我们需要通过.value来访问这个值。这是因为ref返回的是一个包含.value属性的响应式对象,而不是一个基本数据类型的值。
reactive是Vue3提供的一种用于包装对象的响应式对象的实现方式。在Vue3中,使用reactive可以将对象包装为一个响应式对象。当这个对象的属性发生变化时,Vue3会自动更新视图中相应的内容。
下面是一个使用reactive的例子:
<template>
<div>
<p>{{ user.name }}p>
<button @click="updateUserName">更新button>
div>
template>
<script>
import { reactive } from 'vue';
export default {
setup() {
const user = reactive({
name: 'John Doe',
age: 30
});
const updateUserName = () => {
user.name = 'Jane Doe';
};
return {
user,
updateUserName
};
}
};
script>
在这个例子中,我们使用了reactive来包装一个包含name和age两个属性的对象。在setup函数中,我们将reactive返回的响应式对象作为组件实例的一个属性,同时也将updateUserName函数返回给模板。当updateUserName函数被调用时,user对象的name属性会被更新为’Jane Doe’,并且视图中显示的内容也会被更新。
需要注意的是,在使用reactive包装对象时,所有的属性都会被包装为响应式对象,包括嵌套的对象和数组。这意味着当嵌套对象或数组的属性发生变化时,也会触发相应的视图更新。
下面是一个包含嵌套对象和数组的例子:
<template>
<div>
<p>{{ user.name }}p>
<p>{{ user.address.city }}p>
<ul>
<li v-for="hobby in user.hobbies" :key="hobby">{{ hobby }}li>
ul>
<button @click="updateUser">更新button>
div>
template>
<script>
import { reactive } from 'vue';
export default {
setup() {
const user = reactive({
name: 'John Doe',
age: 30,
address: {
city: 'New York',
country: 'USA'
},
hobbies: ['reading', 'swimming', 'hiking']
});
const updateUser = () => {
user.name = 'Jane Doe';
user.address.city = 'San Francisco';
user.hobbies.push('yoga');
};
return {
user,
updateUser
};
}
};
script>
在这个例子中,我们使用reactive来包装一个包含嵌套对象和数组的对象。在setup函数中,我们将reactive返回的响应式对象作为组件实例的一个属性,同时也将updateUser函数返回给模板。当updateUser函数被调用时,user对象的name属性、address对象的city属性和hobbies数组的内容都会被更新,并且视图中显示的内容也会被更新。
在使用ref和reactive时,需要注意它们之间的区别。ref适用于包装基本数据类型,而reactive适用于包装对象。此外,ref返回的是一个包含.value属性的响应式对象,而reactive返回的是一个包装后的响应式对象。
下面是一个使用ref和reactive的区别的例子:
<template>
<div>
<p>{{ message }}p>
<p>{{ user.name }}p>
<button @click="updateData">更新button>
div>
template>
<script>
import { ref, reactive } from 'vue';
export default {
setup() {
const message = ref('Hello, World!');
const user = reactive({
name: 'John Doe',
age: 30
});
const updateData = () => {
message.value = 'Hello, Vue3!';
user.name = 'Jane Doe';
};
return {
message,
user,
updateData
};
}
};
script>
在这个例子中,我们同时使用了ref和reactive。当updateData函数被调用时,我们使用ref更新了message的值,同时也使用reactive更新了user对象的name属性的值。需要注意的是,在更新message的值时,我们需要使用.value来访问它的值,而在更新user对象的name属性的值时,我们直接使用了对象的属性访问方式。
Vue 3 中的 toRefs 函数是一个非常有用的工具,它可以将一个响应式对象转换为一组响应式属性。这个函数可以用于将父组件中的响应式对象传递给子组件,并在子组件中以单独的响应式属性的形式使用它们。
在 Vue 3 中,我们可以使用 ref 和 reactive 来创建响应式数据。ref 可以用于创建单个值的响应式数据,而 reactive 则可以用于创建包含多个属性的响应式对象。
但是,在某些情况下,我们希望将一个响应式对象的属性单独作为响应式属性使用,而不是将整个对象作为一个响应式数据使用。这时就可以使用 toRefs 函数。
toRefs 函数的作用是将一个响应式对象转换为一个对象,该对象的属性均为单独的响应式属性,这些属性与原始响应式对象的属性具有相同的响应式性质。
下面是一个示例,演示了如何使用 toRefs 函数将一个响应式对象转换为一组响应式属性:
<template>
<div>
<p>Count: {{ count }}p>
<button @click="increment">Incrementbutton>
<ChildComponent :propsData="toRefs(childData)" />
div>
template>
<script>
import { reactive, toRefs } from 'vue';
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent,
},
setup() {
const data = reactive({
count: 0,
message: 'Hello!',
});
const childData = reactive({
name: 'Child',
age: 10,
});
const increment = () => {
data.count++;
};
return {
...toRefs(data),
childData,
increment,
};
},
};
script>
在这个例子中,父组件的 data 对象包含一个 count 属性,表示一个计数器。父组件通过 toRefs 函数将这个对象转换为一组响应式属性,并将这些属性传递给了子组件。子组件可以像使用普通的响应式属性一样使用这些属性。
需要注意的是,toRefs 函数返回的对象中的属性并不是响应式的,而是与原始响应式对象的属性具有相同的响应式性质。这意味着,如果原始响应式对象的属性被更新了,返回的对象中的属性也会被更新。但是,如果返回的对象中的属性被直接更新了,原始响应式对象中的对应属性不会被更新。
Vue3的响应式原理——一定要背下来!
Vue3的响应式原理是通过Proxy(代理)对对象的属性值进行读写、添加、删除、进行劫持,通过Reflect(反射)动态对被代理对象的属性值进行特定的操作,由于Proxy和Reflect不支持IE浏览器,这也是Vue3不支持IE浏览器的主要原因之一!