vue响应式形成条件
-
函数和数据的直接关联(比如computed里面也是要传函数的)
- 被监控的函数
- 源码体现
- vue2的watch
- vue3的effect
- 直接体现
- render函数
- computed回调
- watchEffect
- watch
- 源码体现
- 函数运行期间用到了响应式函数
- ref(computed本质)
- reactive(props本质)
- 响应式数据变化会导致函数重新运行
- 总结判断方法
- 先看是否有被监控函数
- 再看监控函数方法里面的响应式数据
- 最后看响应式数据变化是否会导致函数重新执行
- 被监控的函数
-
实践分析代码
// 父组件
<template>
<children :count="count"></children>
<button @click="changeParentCount"></button>
</template>
<script setup lang="ts">
import children from "./children.vue";
import { ref } from "vue";
const count = ref(0);
const changeParentCount = () => {
count.value++;
};
</script>
<style lang="scss"></style>
// 子组件
<template>
<div>得到的传入的属性:{{ count }}</div>
<div>测试的数据:{{ doubleCount }}</div>
</template>
<script lang="ts" setup>
import { ref, defineProps, watchEffect, withDefaults, computed } from "vue";
// 通识:响应式数据一定一个对象,不管是reactive还是ref,ref访问的是一个.value的对象
// 前置条件:
const props = withDefaults(
defineProps<{
count: number;
}>(),
{
count: 0,
},
);
// 1
// const doubleCount = ref(props.count * 2);
// 分析:这个结果不生效,因为没有和render函数直接关联
// 2
// const doubleCount = ref(0);
// watchEffect(() => {
// doubleCount.value = props.count * 2;
// });
/*
分析:这个结果生效
watchEffect里面有被监控的函数(满足1);
函数运行期间用到响应式数据Props.count(满足2)
props.count的变化会导致被监控函数的箭头函数重新运行,
与render函数关联的doubleCount改变会导致render函数重新运行
*/
// 3.1
/* function useDouble(count: any) {
const doubleCount = ref(count * 2);
watchEffect(() => {
doubleCount.value = count * 2;
});
return doubleCount;
}
const doubleCount = useDouble(props.count); */
/**
* 分析:先从函数入手,watchEffect里面使用到了count,
* 但count是一个非响应式对象(没有完成对响应式对象的读取)
* 如果要让这个函数可以实现响应式,应该传入props(见3.1)
*/
// 3.2
/* function useDouble(data: any) {
const doubleCount = ref(data.count * 2); //这边的读取只是一次初始化
watchEffect(() => {
doubleCount.value = props.count * 2;
});
return doubleCount;
}
const doubleCount = useDouble(props); //传入对象,vueUse里面也这么做 */
// 四、
// const doubleCount = computed(() => props.count * 2);
/**
* 分析
* 有受监控的函数(computed里面受监控的函数)
* 受监控的函数里面有用到响应式数据props(对象)
* computed返回的是一个响应式数据,这个响应式数据的变化会导致render函数重新运行
*/
// 五、
function useDouble(count: any) {
const doubleCount = computed(() => count * 2);
return doubleCount;
}
const doubleCount = useDouble(props.count);
/**
* computed里面有受监控的函数
* 受监控的函数里面没有响应式数据(对象形式)
*/
</script>
<style scoped></style>