Skip to content

几个例子理解 Vue 的响应式

Published:

前言

在 Vue.js 中,响应式的核心是将数据和函数关联起来。简单来说,当我们使用 Vue.js 的 template 时,它实际上是一个 render 函数,这个函数依赖于响应式数据。当数据发生变化时,这个 render 函数会重新运行,从而更新视图。

但要注意,并不是所有函数都能自动关联到数据。在 Vue.js@2 中,是通过 watcher 监控函数,在 Vue.js@3 中,使用的是 effect,比如 rendercomputedwatchEffectwatch

另外,并不是所有数据都可以被关联。只有那些定义为响应式的数据,并且在函数中被使用,才能建立这种关联。

第一个案例

<script setup>
const props = defineProps({
  count: Number,
});

const doubleCount = ref(props.count * 2);
</script>

在这个例子中,doubleCount 是通过 props.count 初始化的。但是,点击按钮后,doubleCount 不会变化。这是因为 doubleCount 只是初始化时依赖了 props.count,是一个原始值,而没有在之后的过程中与 props.count 关联。

简单来说,数据与数据之间并没有自动建立起关联,这在 JavaScript 中是无法实现的,那么 Vue.js 也就无法实现。

第二个案例

<script setup>
const doubleCount = ref(0);
watchEffect(() => {
  doubleCount.value = props.count * 2;
});
</script>

这里,我们使用了 watchEffect。当你点击按钮时,UI 上的 doubleCount 会跟着变化。这是因为 watchEffect 的回调函数会被 watchEffect 监控,而这个回调函数中使用了响应式的 props.count。所以,watchEffect 会跟踪 props.count 的变化,并在数据改变时重新执行回调函数,从而更新 doubleCount,最后重新调用 render 函数渲染视图。

第三个案例

<script setup>
function useDouble(count) {
  const doubleCount = ref(count * 2);

  watchEffect(() => {
    doubleCount.value = count * 2;
  });

  return doubleCount;
}

const doubleCount = useDouble(props.count);
</script>

在这个例子中,useDouble 函数返回了一个 doubleCount。但是,点击按钮后,doubleCount 不会更新。

这是因为 count 传入 useDouble 时也是原始值,而不是响应式数据。watchEffect 只会在函数内部监控 count 的变化,但这里 count 只是一个普通的数字,没有响应式能力。因此,doubleCount 不会随着 props.count 的变化而更新,render 函数也不会重新调用。

第四个案例

const doubleCount = computed(() => props.count * 2);

这里,我们使用了 computedcomputed 属性可以根据 props.count 自动更新。当 props.count 变化时,computed 中的函数也会重新运行,从而更新 doubleCount。由于 template 依赖了 doubleCount,所以 render 函数会被重新调用,视图也会随之更新。

第五个案例

function useDouble(count) {
  const doubleCount = computed(() => count * 2);
  return doubleCount;
}

const doubleCount = useDouble(props.count);

在这个例子中,useDouble 函数返回了一个 computed 属性。由于传递给 useDoublecount 仍然是原始值,computed 也不会自动跟踪 props.count 的变化。要确保 doubleCount 更新,我们需要确保 count 是响应式的。

解决

要让 doubleCount 随着 props.count 的变化而更新,你可以使用 computed 属性,或者添加一个 watch 来监控 props.count 的变化,并更新 doubleCount。示例代码:

const doubleCount = ref(props.count * 2);
watch(() => props.count, (doubleCount.value = props.count * 2));