Vue 2 中动态新增属性丢失响应性原因探究

在 Vue.js 的开发过程中,数据的响应性是核心特性之一。Vue 通过其内部的响应式系统,能够自动追踪数据的变化,并将这些变化实时反映到视图上。然而,当涉及到动态新增属性时,情况可能会变得复杂。本文将通过一个具体的实验案例,深入探讨 Vue 2 中动态新增属性的响应性表现。

实验设计

为了验证 Vue 2 中动态新增属性的响应性,我们设计了一个包含三个场景的实验。实验的核心是一个名为 formData 的对象,它最初只包含一个空对象,而后续的属性将通过不同的方式动态添加。

vue 复制代码
<template>
    <div class="demo">
        <h1>vue2中动态新增属性是否是响应式的?</h1>
        {{ formData }}
        <div class="case">
            <h3>场景1:新增加的属性没有被直接赋值【有响应性】</h3>
            <input v-model="formData.newProperty" placeholder="输入测试">
            <button @click="$forceUpdate()">强制更新</button>
            <p>视图显示:{{ formData.newProperty || '无值' }}</p>
        </div>
        <div class="case">
            <h3>场景2:新增加的属性先通过更新按钮赋值【没有响应性】</h3>
            <button @click="changeData">更新By = </button>
            <input v-model="formData.newProperty2" placeholder="输入测试">
            <button @click="$forceUpdate()">强制更新</button>
            <p>视图显示:{{ formData.newProperty2 || '无值' }}</p>
        </div>
        <div class="case">
            <h3>场景3:新增加的属性先通过更新按钮赋值【有响应性】</h3>
            <button @click="changeDataBySet">更新By Vue.set</button>
            <input v-model="formData.newProperty3" placeholder="输入测试">
            <button @click="$forceUpdate()">强制更新</button>
            <p>视图显示:{{ formData.newProperty3 || '无值' }}</p>
        </div>
    </div>
</template>

  <script>
    export default {
        data() {
            return {
                formData: {
                    // newProperty: '', // 如果不在这里声明,则不会更新视图
                }
            };
        },
        methods: {
            changeData() {
                this.formData.newProperty2 = '新值';
            },
            changeDataBySet() {
                this.$set(this.formData, 'newProperty3', '新值');
            },
        }
    };
  </script>

  <style>
  .demo {
    padding: 20px;
    border: 1px solid #eee;
  }
  .case {
    margin: 20px 0;
    padding: 15px;
    border: 1px dashed #ccc;
  }
  </style>

场景 1:直接在模板中新增属性

在第一个场景中,我们尝试直接在模板中通过 v-model 绑定一个尚未声明的属性 newProperty。按照 Vue 的响应式原理,如果一个属性在 data 中未被声明,Vue 无法追踪它的变化,从而导致视图无法自动更新。然而,我们通过实验发现,尽管 newProperty 未在 data 中预先声明,但当我们在输入框中输入内容时,视图仍然能够正常更新并显示输入的值。这表明,Vue 在某些情况下能够自动处理未声明的属性,并赋予其响应性。

场景 2:通过方法动态新增属性(无响应性)

在第二个场景中,我们通过一个按钮点击事件调用 changeData 方法,动态为 formData 添加一个新属性 newProperty2 并赋值。随后,我们尝试通过 v-model 绑定这个新属性,并观察视图的变化。实验结果显示,当我们在输入框中输入内容时,视图无法自动更新。这说明,通过普通的方式动态新增属性,Vue 无法自动追踪其变化,因此该属性不具备响应性。

场景 3:通过 Vue.set 动态新增属性(有响应性)

在第三个场景中,我们使用 Vue 提供的 $set 方法动态为 formData 添加一个新属性 newProperty3 并赋值。与第二个场景类似,我们通过 v-model 绑定这个新属性,并观察视图的变化。实验结果显示,当我们在输入框中输入内容时,视图能够正常更新并显示输入的值。这表明,通过 $set 方法动态新增的属性能够被 Vue 正确追踪,从而具备响应性。

实验结果分析

通过上述三个场景的实验,我们可以得出以下结论:

  1. 直接在模板中新增属性 :Vue 能够自动处理未声明的属性,并赋予其响应性。这可能是因为 Vue 在解析模板时,会自动将模板中绑定的属性注册为响应式属性,即使这些属性在 data 中未被预先声明。
  2. 通过普通方式动态新增属性 :这种方式新增的属性不具备响应性。这是因为 Vue 的响应式系统在初始化时,只会对 data 中声明的属性进行依赖追踪。如果后续动态添加的属性未经过 Vue 的响应式处理,Vue 将无法追踪其变化。
  3. 通过 $set 方法动态新增属性 :这种方式新增的属性具备响应性。$set 方法是 Vue 提供的一个专门用于动态新增响应式属性的工具。它能够确保新增的属性被 Vue 的响应式系统正确追踪,从而实现视图的自动更新。

总结与建议

Vue 2 中动态新增属性的响应性表现取决于新增属性的方式。直接在模板中新增属性或通过 $set 方法新增属性能够确保响应性,而通过普通方式动态新增属性则不具备响应性。

在实际开发中,为了确保数据的响应性,建议在 data 中预先声明所有可能使用的属性,或者使用 $set 方法动态新增属性。

这样可以避免因响应性问题导致的视图更新异常,提高代码的可维护性和稳定性。

相关推荐
软件技术NINI11 小时前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
招风的黑耳13 小时前
SpringBoot+Vue+MySQL 民宿在线预定平台 完整可运行版(源码+文档)
vue.js·spring boot·mysql
10share1 天前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js
啾咪orJIUMI2 天前
Vue 3 + 高德地图封装实战:点位、区域、Loca 流光与 Vue 信息窗体
前端·vue.js
FRing032 天前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
无懈可击2 天前
Vue 可视化AI表单设计器 FcDesigner v3.6 版本发布,支持导出 SQL功能!
vue.js·开源·ai编程
徐小夕2 天前
JitArchives,一款基于JitWord协同AI文档打造的企业级电子档案系统
前端·vue.js·github
头发还在的女程序员2 天前
基于 Spring Boot + Vue 3 + uni-app 的灵活用工系统:四端架构与业务流程设计
vue.js·spring boot·uni-app·灵活用工·灵工系统
FRing032 天前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
ruanno_top3 天前
点全选,已选的被清空了:Transfer 三态复选框的三个 bug
vue.js