为什么普通对象在 Vue3 中会自动变成响应式?

Pai*_*Joy 4 vue.js vue-reactivity vuejs3 vue-composition-api

这篇文章中有一个例子。它说正常的物体不会有“反应性”。

我在这个codesandbox中做了测试,发现对普通对象(甚至是普通字符串)的改变可以自动改变视图。

<template>
  {{ personName }} <!-- will change to Amy, why? -->
  {{ person.name }} <!-- will change to Amy, why? -->
  {{ personRef.name }}
  {{ personReactive.name }}
  <button @click="changeName('Amy')">changeName</button>
</template>

<script setup>
import { ref, reactive } from "vue";

let personName = "John";
const person = { name: "John" };
const personRef = ref({ name: "John" });
const personReactive = reactive({ name: "John" });
const changeName = (name) => {
  personName = name;
  person.name = name;
  personRef.value.name = name;
  personReactive.name = name;
};
</script>
Run Code Online (Sandbox Code Playgroud)

这怎么发生的?我是否遗漏了 Vue 文档中的某些内容?

我尝试过Vue SFC Playground,它给出了相同的结果。

Fan*_*lix 5

正常变量不会变得被动。真正发生的是由该方法引起的重新渲染changeName()。重新渲染是因为您更改了反应变量的值而引起的。因此,DOM 会更新为正常变量和反应变量正确显示的最新值。

为了说明这一点,我使用以下代码创建了沙箱的分支:

<template>
  {{ personName }}
  {{ person.name }}
  {{ personRef.name }}
  {{ personReactive.name }}
  <button @click="changeReactiveName('Amy')">changeReactiveName</button>
  <button @click="changeNormalName('Fanoflix')">changeNormalName</button>
</template>

<script setup>
import { ref, reactive } from "vue";

let personName = "John";
const person = { name: "John" };
const personRef = ref({ name: "John" });
const personReactive = reactive({ name: "John" });

const changeReactiveName = (name) => {
  personRef.value.name = name;
  personReactive.name = name;
};

const changeNormalName = (name) => {
  personName = name;
  person.name = name;
};
</script>
Run Code Online (Sandbox Code Playgroud)

当您通过调用仅更改非响应变量时changeNormalName(),更改(正确地)不会导致 DOM 重新渲染,并且您将不会看到 DOM 中反映的更改。

调用该changeReactiveName()方法后,DOM 将重新呈现以合并对反应变量所做的更改。因此,DOM 还将呈现您之前更新的非反应变量的新值,并将显示Fanoflix

为了更好地理解,请阅读 Vue 如何处理渲染:文档