computed 计算属性
计算属性是指 基于现有状态派生 (演变) 出新的状态,现有状态发生变化,派生状态重新计算。
computed 接收回调函数作为参数,基于回调函数中使用的响应式数据进行计算属性的创建,回调函数的返回值就是基于现有状态演变出的新状态。
// 定义一个数据
const num = ref(0);
// result 通过计算num动态获得
const result = computed(() => num.value * 2);
- 完整写法
import { ref, computed } from 'vue';export default {setup() {// 响应式数据const firstName = ref('张');const lastName = ref('三');// 计算属性(完整写法,考虑读和写)const fullName = computed({get() {return firstName.value + lastName.value;},set (value) {const nameArr = value.split('-');firstName.value = nameArr[0];lastName.value = nameArr[1];},});// 返回所有的数据和方法,才能使用return { firstName, lastName, fullName }}
}
案例:动态显示名字。
<template><input type="text" v-model="firstName" /><input type="text" v-model="lastName" /><div>姓名:{{ name }}</div>
</template><script>
import { ref, computed } from 'vue';export default {setup() {const firstName = ref('');const lastName = ref('');// 姓名通过计算属性获得const name = computed(() => firstName.value + lastName.value);return { firstName, laseName, name }}
}
</script>
watch 监听状态
watch 方法用于监听响应式数据的变化,数据发生变化时触发。
Vue2 的 watch 是一个配置项,Vue3 的 watch 是一个方法。
# 语法格式
watch([监视对象], fn{监视的回调}, {监视的配置});
监听 ref 的响应式数据
监听 ref 数据时,不能使用
.value
,因为监听的是 value 的值,而不是 ref 数据。
- 监听多个值时,newValue 和 oldValue 会接收一个数组,参数是监听的每一项。
使用 watch 方法监听基于 ref 创建的响应式数据 (基本数据类型)。
<template><input type="text" v-model="str">
</template><script>
import { ref, watch } from 'vue';export default {setup() {const str ref('');// 监听表单内容 strwatch(str, (newValue, oldValue) => {console.log(newValue, oldValue);}, {// 监听的配置immediate: true,deep: true});// 返回所有的数据和方法,才能使用return { str }}
}
</script>
使用 watch 监听基于 ref 创建的响应式数据 (引用数据类型)。
import { ref, watch } from "vue";export default {setup() {const person = ref({ name: '张三' });// 监听watch(person.value, (newValue, oldValue) => {console.log(newValue, oldValue);}, {// 监听的配置immediate: true,deep: true});// 返回所有的数据和方法,才能使用return { person }},
};
使用 watch 监听响应式数据内部的具体属性 (基本数据类型)
import { ref, watch } from "vue";export default {setup() {const person = ref({ name: '张三' });// 监听watch(() => person.value.name,(newValue, oldValue) => {console.log(newValue, oldValue);});// 返回所有的数据和方法,才能使用return { person }},
};
监听 reactive 的响应式数据
import { ref, watch } from "vue";export default {setup() {const person = reactive({ name: '张三' });// 监听watch(person, (newValue, oldValue) => {console.log(newValue, oldValue);});// 返回所有的数据和方法,才能使用return { person }},
};
监听 reactive 时存在的问题
坑:监听 reactive 时,oldValue 无法正确获取,都是最新值。(Vue3的遗留问题)
- 解决方案:
watch 的 参数1 使用
() => 对象名.属性名
监听单个属性,但是要使用 deep 深度监听。(虽然麻烦,但是有效)
const person = ref({ name: '张三', age: 18 });watch(// 参数一写法解决 oldValue 值无法获取[() => person.name, () => person.age],(newValue, oldValue) => {console.log(newValue, oldValue);});
坑:使用 reactive 时,强制开启 deep 深度监视,且 deep 无法被关闭。(Vue3的遗留问题)
import { ref, watch } from "vue";export default {setup() {const person = reactive({ name: '张三' });// 监听watch(person, (newValue, oldValue) => {console.log(newValue, oldValue);}, {deep: false, // 无效,无法关闭});// 返回所有的数据和方法,才能使用return { person }},
};
watchEffect 监听状态
watchEffect 函数在页面加载完成后和数据更新时调用。
watch 和 watchEffect 的区别:
- watch:既要指明监视的属性,也要指明监视的回调。
- watchEffect:不用指明监视哪个属性,监视的回调中用到哪个属性,就监听哪个属性。
watchEffect 和 computed 的区别:
- computed 注重计算出来的值(回调函数的返回值),所以必须要写返回值。
- watchEffect 更注重的是过程(回调函数的函数),所以不用写返回值。
# 语法格式
watchEffect(() => {console.log('watchEffect 函数执行了');
})
<template><h1>{{ person.name }}</h1><button @click="updatePerson">点击更新名字</button>
</template><script>
import { reactive, watchEffect } from "vue";
export default {setup() {// 响应式数据let person = reactive({name: "张三",age: 18,job: {j1: {salary: 20,},},});// 监视watchEffect(() => {console.log("watchEffect执行了");console.log(person.name);});// 更新名字const updatePerson = () => {person.name = "李四";};return { person, updatePerson };},
};
</script>
toRef 函数
创建一个 ref 对象,其 value 值指向另一个对象中的某个属性。
大白话解释:toRef 方法用于将响应式数据内部的普通数据转化为响应式数据,并且转换后的数据和原始数据存在引用关系,存在引用关系意味着当原始数据发生变化后,toRefs 转换后的数据也会跟着变化。
应用:要将响应式对象中的某个属性单独提供给外部使用时。
// 语法
const name = toRef(对象名, '属性名')
<template><h1>{{ name }}</h1><h1>{{ age }}</h1><h1>{{ salary }}</h1>
</template><script>
import { reactive, toRef } from 'vue'
export default {name: 'App',setup() {let person = reactive({name: '张三',age: 18,job: {j1: {salary: 20}}})return {pname: toRef(person, 'name'),age: toRef(person, 'age'),salary: toRef(person.job.j1, 'salary')}},
}
</script>
toRefs 函数
toRefs方法接收引用数据类型的响应式数据,它可以将数据中的第一层属性全部转换为响应式数据,返回值是一个对象,对象中存储了所有转换之后的响应式数据。
export default {setup() {const person = reactive({name: "张三",brand: {title: "宝马",year: 1}});return {...toRefs(person),...toRefs(person.brand) // 转换第二层数据为响应式}}
}