ref和reactive

vue3中响应式数据需要使用ref或reactive包裹数据。ref 用于创建基本数据类型、对象。reactive 用于创建对象类型。

Vue3中的ref和reactive都是用于创建响应式数据的不同方式,它们的区别主要在于处理的数据类型和访问/修改数据的方式:

1,数据类型:
ref:可以用来包装任何类型的值(包括基本类型如字符串、数字、布尔值以及引用类型如对象或数组)。返回的是一个Ref对象,该对象包含 .value 属性,这个属性是原始值的容器。
reactive:只能用来包装对象(包括嵌套的对象和数组),它会返回一个代理对象,这个代理对象与原对象具有相同的结构和属性,但这些属性已经是响应式的。

2,访问和修改数据:
ref:需要通过.value来获取或设置其内部值。例如 const count = ref(0); count.value++;。
reactive:可以直接通过点.操作符访问或修改其属性。例如 const user = reactive({ name: ‘John’, age: 30 }); user.age++;。

3,使用场景:
ref:适合于简单的独立变量或者不需要深度响应式的场景。
reactive:当需要创建深层次嵌套的对象结构,并且希望整个对象及所有子属性都成为响应式时使用。

4,在模板中使用:

ref:在模板中需要解包,即 。

reactive:在模板中可以直接访问,无需解包,即 。
总结来说,ref提供了对单一值进行响应式封装的方法,而reactive则提供了对复杂对象进行深度响应式化的能力。

toRefs

oRefs 是 Vue3 Composition API 中的一个辅助函数,用于将一个 reactive 对象转换为一组 ref。这在你需要将 reactive 对象中的各个属性作为独立的 ref 使用时非常有用。

import { reactive, toRefs } from 'vue';

export default {
setup() {
// 创建一个响应式对象
const user = reactive({
name: 'John Doe',
age: 30,
address: {
street: '123 Main St',
city: 'Anytown'
}
});

// 使用 toRefs 将 reactive 对象转换为 ref 对象集合
const userRefs = toRefs(user);

// 现在你可以像操作 ref 一样操作 user 的各个属性
console.log(userRefs.name.value); // John Doe
userRefs.age.value++; // 用户年龄加一

return {
...userRefs // 在模板中可以直接使用 {{ name }} 和 {{ age }}
};
}
}

在这个例子中,toRefs(user) 返回一个新的对象,其属性与原 reactive 对象的属性相同,但每个属性现在都是一个 ref。这意味着你可以在模板中直接解包并使用它们(如 ),同时在逻辑部分可以利用 .value 进行读写操作。

toRef

toRef 用于将一个响应式对象的某个属性转换为一个独立的 ref 对象。
当你想要从一个大的响应式对象中提取出一个单独的属性,并且保持该属性与原始对象中的对应属性同步时,使用 toRef 很有用。
语法:const newRef = toRef(source, key)
source 是源响应式对象。
key 是要从 source 中提取出来的属性名。
返回值是一个新的 ref 对象,其 .value 属性指向原对象 source[key] 的值。

import { reactive, toRef } from 'vue';

const user = reactive({ name: 'John Doe', age: 30 });
const ageRef = toRef(user, 'age');

console.log(ageRef.value); // 输出:30
ageRef.value++; // 修改 ageRef 也会修改 user.age

计算属性

Vue3 中的计算属性(Computed Properties)用于处理基于响应式状态衍生出的新值。当依赖的状态发生变化时,计算属性会自动重新计算结果,并更新到视图中。在 Vue3 的 Composition API 中,计算属性通过 computed 函数来创建。
以下是一个基本的 Vue3 计算属性的使用示例:

import { ref, computed } from 'vue';

export default {
setup() {
// 创建两个响应式引用
const firstName = ref('John');
const lastName = ref('Doe');

// 创建一个计算属性,它依赖于 firstName 和 lastName
const fullName = computed(() => `${firstName.value} ${lastName.value}`);

return {
firstName,
lastName,
fullName // 在模板中可以直接使用 {{ fullName }}
};
}
}

在这个例子中,fullName 是一个计算属性,它的值是基于 firstName 和 lastName 的组合。每当 firstName 或 lastName 改变时,fullName 的值也会自动更新,而无需手动重新计算。
另外,在 Vue3 中计算属性也可以具有 setter:

const fullName = computed({
get: () => `${firstName.value} ${lastName.value}`,
set: (newValue) => {
const parts = newValue.split(' ');
firstName.value = parts[0];
lastName.value = parts[1];
}
});

除了 getter 外还定义了一个 setter,这意味着你不仅可以从计算属性获取合并后的全名,还可以设置全名,该设置操作会自动分解并分别更新 firstName 和 lastName 的值。

watch

Vue3 中的 watch 函数是用来监听和响应数据变化的,它允许开发者在指定的数据或计算属性发生变化时执行相应的回调函数。当被观察的数据发生变化时,Vue 会自动调用定义好的回调函数,并传递新的值(newVal)和旧的值(oldVal)作为参数。
以下是一个 Vue3 中使用 watch 的基本示例:

import { ref, watch } from 'vue';

export default {
setup() {
const count = ref(0);

// 监听 count 值的变化
watch(count, (newCount, oldCount) => {
console.log(`Count changed from ${oldCount} to ${newCount}`);
// 在这里可以进行其他逻辑处理,如更新视图、发送网络请求等
});

// 更新 count 的值以触发 watch 回调
function increment() {
count.value++;
}

return {
count,
increment
};
}
}

在这个例子中,watch 函数用于监听 count 变量的变化。每当 count 的 .value 属性改变时,就会触发回调函数,并打印出新旧值的变化情况。
除了监听单个变量外,watch 还可以监听对象或数组的深层变化,以及同时监听多个源数据并根据它们的变化采取行动。此外,还可以通过配置项来精细控制监听的行为,例如深度监听、延迟执行、在组件生命周期中的不同阶段启用或禁用监听器等。

watch配置项

Vue3 中 watch 函数的配置项允许开发者对监听行为进行更细致的控制,以下是一些常见的配置项:

deep

deep (boolean):
默认值:false
如果设置为 true,Vue 将深度监听对象或数组内部的变化。这意味着当对象的嵌套属性或数组元素发生变化时,回调函数也会被触发。

immediate

immediate (boolean):
默认值:false
当设置为 true 时,会在 watch 配置后立即执行回调函数一次,即便依赖的数据在声明时并未发生变化。

flush

flush:
在 Vue3 中,flush 是一个可选的字符串参数,用于指定何时执行 watch 回调。
'pre': 在当前 tick 的 DOM 更新之前执行。
'post': 在当前 tick 的 DOM 更新之后执行(默认)。
'sync': 立即同步执行,通常仅限于用户自定义 flush 队列中使用。

onTrack 和 onTrigger

onTrack 和 onTrigger:
这两个配置项主要用于调试和跟踪响应式系统的行为。
onTrack 会在响应式依赖收集期间调用,提供关于正在访问哪个属性的信息。
onTrigger 会在响应式依赖更新时调用,告知哪些依赖项引发了更新。

handler

handler (必需):
类型:(newValue: any, oldValue: any) => void
回调函数,在被观察的数据变化时执行。它接收新的值和旧的值作为参数。

示例:

import { ref, watch } from 'vue';

export default {
setup() {
const user = ref({
name: 'John Doe',
address: {
street: '123 Main St'
}
});

watch(() => user.value,(newUser, oldUser, onCleanup) => {
console.log('New user:', newUser);
// 在此处处理变更

// 如果需要清理资源,可以在回调函数内使用 onCleanup
onCleanup(() => {
// 清理逻辑...
});
},
{
deep: true, // 深度监听
immediate: true, // 立即执行回调
flush: 'post', // 指定执行时机
}
);

return {
user
};
}
}

上述示例中并没有展示 onTrack 和 onTrigger 的用法,因为它们主要用于调试和分析响应式系统的内部工作原理,而非日常开发中的常见配置项。

监视reactive数据:

import { reactive, watch } from 'vue';

// 创建一个响应式对象
const state = reactive({
count: 0,
nested: {
message: 'Hello',
},
});

// 监视整个state对象的变化
watch(state, (newValue, oldValue) => {
console.log('State changed:', newValue, oldValue);
});

// 如果只想监视嵌套属性的变化,可以指定getter函数,并开启深度监听
watch(
() => state.nested.message,
(newMessage, oldMessage) => {
console.log('Nested message changed:', newMessage, oldMessage);
},
{ deep: true }
);

路由

安装vue-router

npm install vue-router@next -S