目录
1.2.5 关于侦听ref定义的响应式数据是否添加 .value
1.2.6 情况三:侦听reactive定义的一个响应式数据的全部属性
1.2.7 情况四:侦听reactive所定义的一个响应式数据中的某个属性
1.2.8 情况五:侦听reactive所定义的一个响应式数据中的某些属性
一、常用Composition API(2)
1.1 computed函数
与Vue2.x中的computed配置功能一致
Vue2中的计算属性及其案例练习:Vue知识点整理(一)- Vue核心(3)- 计算属性
1.1.1 案例练习
<template>
姓:<input type="text" v-model="person.firstName" />
<br />
名:<input type="text" v-model="person.lastName" />
<br />
<span>全名:{{ person.fullName }}</span>
<br />
全名:<input type="text" v-model="person.fullName" />
</template>
<script>
import { computed, reactive } from "vue";
export default {
name: "App",
setup() {
// 数据
let person = reactive({
firstName: "冰",
lastName: "墩墩",
});
// 计算属性 - 简写(不考虑计算属性被修改的情况)
/* person.fullName = computed(() => {
return person.firstName + "-" + person.lastName;
}); */
// 计算属性 - 完整写法
person.fullName = computed({
get() {
return person.firstName + "-" + person.lastName;
},
set(value) {
const nameArr = value.split("-");
person.firstName = nameArr[0];
person.lastName = nameArr[1];
},
});
return { person };
},
};
</script>
1.2 watch
与Vue2.x中watch配置功能一致
Vue2中的侦听属性及其案例练习:Vue知识点整理(一)- Vue核心(3)- 侦听
1.2.1 两个注意点
-
监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
-
监视reactive定义的响应式数据中某个属性时:deep配置有效
1.2.2 语法
watch(侦听对象, (newValue, oldValue) => {侦听回调}, { immediate: true, deep: tue });
1.2.3 情况一:侦听ref定义的一个响应式数据
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点击+1</button>
</template>
<script>
import { computed, reactive, ref, watch } from "vue";
export default {
name: "App",
setup() {
// 数据
let sum = ref(0);
// 监视
// 情况一:侦听ref定义的一个响应式数据
watch(sum, (newValue, oldValue) => {
console.log("sum发送改变", newValue, oldValue);
});
return {
sum,
};
},
};
</script>
由图示可看出,sum发送改变时,watch是能够侦听到sum发生变化
1.2.4 情况二:侦听ref定义的多个响应式数据
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点击+1</button>
<hr />
<h2>{{ msg }}</h2>
<button @click="msg += '!'">点击添加!</button>
</template>
<script>
import { computed, reactive, ref, watch } from "vue";
export default {
name: "App",
setup() {
// 数据
let sum = ref(0);
let msg = ref("测试信息");
// 监视
// 情况二:侦听ref定义的多个响应式数据
watch([sum, msg], (newValue, oldValue) => {
console.log("sum或msg发送改变", newValue, oldValue);
});
return {
sum,
msg,
};
},
};
</script>
由图示可看出,sum或msg发送改变时,watch是能够侦听到sum或msg发生变化
如果要打开页面立马执行需要添加 immediate参数,即:
// 情况二:监视ref定义的多个响应式数据
watch(
[sum, msg],
(newValue, oldValue) => {
console.log("sum或msg发送改变", newValue, oldValue);
},
{ immediate: true }
);
1.2.5 关于侦听ref定义的响应式数据是否添加 .value
侦听ref对象是 基本类型 的,那么侦听对象不能添加 .value
- 因为当侦听ref对象是 基本类型 时,不添加 .value 侦听到的是RefImpl实例对象, 所以对象里面任意属性的修改都能被侦听到;如果添加了 .value 侦听到的对象里面属性的值
侦听ref对象是 对象类型 的,那么侦听对象需要添加 .value 或 添加配置项 deep:true
- 因为当侦听ref对象是 对象类型 时,不添加 .value 侦听到的是 RefImpl实例对象, 但侦听不到RefImpl实例对象 中的 value属性 内的 Proxy对象;如果添加了 .value 侦听对象就是 Proxy对象
1.2.6 情况三:侦听reactive定义的一个响应式数据的全部属性
注意:
- 此处无法正确的获取用oldValue
- 强制开启了深度监视(deep配置无效)
<template>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>零用钱:{{ person.item.wallet.money }}</h2>
<button @click="person.name += '!'">姓名添加上!</button>
<button @click="person.age++">年龄增长</button>
<button @click="person.item.wallet.money++">零花钱增加</button>
</template>
<script>
import { reactive, watch } from "vue";
export default {
name: "App",
setup() {
// 数据
let person = reactive({
name: "周星星",
age: 25,
item: {
wallet: {
money: 100,
},
},
});
/*
情况三:侦听reactive定义的一个响应式数据的全部属性
注意:
1.此处无法正确的获取用oldValue
2.强制开启了深度监视(deep配置无效)
*/
watch(
person,
(newValue, oldValue) => {
console.log("person发生变化", newValue, oldValue);
},
{ deep: false } // 此处deep配置无效
);
return { person };
},
};
</script>
由图示可看出,即使添加了配置项 deep:true 仍旧会侦听到处于深层次结构内 money属性 的改变
1.2.7 情况四:侦听reactive所定义的一个响应式数据中的某个属性
可直接将 情况三中的 watch函数替换为如下代码:
// 情况四:侦听reactive所定义的一个响应式数据中的某个属性
watch(
() => person.age,
(newValue, oldValue) => {
console.log("person发生变化", newValue, oldValue);
}
);
由图示可看出,成功触发只侦听reactive所定义person数据中的age属性
1.2.8 情况五:侦听reactive所定义的一个响应式数据中的某些属性
可直接将 情况四中的 watch函数替换为如下代码:
// 情况五:侦听reactive所定义的一个响应式数据中的某些属性
watch([() => person.name, () => person.age], (newValue, oldValue) => {
console.log("person发生变化", newValue, oldValue);
});
由图示可看出,成功触发侦听reactive所定义person数据中的name属性和age属性
1.2.9 特殊情况
侦听reactive所定义的一个响应式数据中的 对象类型属性
此处由于侦听的是reactive所定义的对象中的某个属性,所以deep配置有效
// 特殊情况
watch(
() => person.item,
(newValue, oldValue) => {
console.log("person发生变化", newValue, oldValue);
},
{ deep: true } // 此处由于侦听的是reactive所定义的对象中的某个属性,所以deep配置有效
);
如果未添加deep配置,则会导致侦听失效
// 特殊情况 - 未添加deep配置
watch(
() => person.item,
(newValue, oldValue) => {
console.log("person发生变化", newValue, oldValue);
}
// { deep: true } // 此处由于侦听的是reactive所定义的对象中的某个属性,所以deep配置有效
);
1.3 watchEffect函数
1.3.1 watchEffect 和 watch
- watch:纪要指明侦听的属性,也要指明侦听的回调
- watchEffect:不用指明侦听哪个属性,侦听的回调用到哪个属性,那就侦听哪个属性
watchEffect有点像 computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
1.3.2 案例练习
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点击+1</button>
<hr />
<h2>{{ msg }}</h2>
<button @click="msg += '!'">点击添加!</button>
<hr />
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>零用钱:{{ person.item.wallet.money }}</h2>
<button @click="person.name += '!'">姓名添加上!</button>
<button @click="person.age++">年龄增长</button>
<button @click="person.item.wallet.money++">零花钱增加</button>
</template>
<script>
import { reactive, ref, watch, watchEffect } from "vue";
export default {
name: "App",
setup() {
// 数据
let sum = ref(0);
let msg = ref("测试信息");
let person = reactive({
name: "周星星",
age: 25,
item: {
wallet: {
money: 100,
},
},
});
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(() => {
const x1 = sum.value;
const x2 = person.item.wallet.money;
console.log("watchEffect所指定的回调执行了");
});
return {
sum,
msg,
person,
};
},
};
</script>