Vue中data的响应式系统

Vue组件中,data必须是函数以使数据响应式。若在created钩子后赋值,如`profile`,则不会加入响应式系统。Vue提供`$set`方法能在运行时使数据响应式,但最佳实践是在data中预先声明。示例比较了`Object.assign`与`Vue.$set`的效果,显示在实例创建后动态添加的数据如何影响视图更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Vue中声明组件时,如果使用了对象类型的data选项,模板将找不到data中被声明的数据,如果使用了支持Vue模板的语法检查,开发者将得到错误提示"data proerty in component must be a function"。
Vue会递归地将data选择中的数据加入响应式系统,但这些数据应该是声明时即存在的,下面来看一段提示代码。

<div id="app">
    <p>{{title}}</p>
    <p>{{profile}}</p>
  </div>
  <script>
    const vue = new Vue({
      el:"#app",
      data() {
        return {
          title :"A Vue App",
        }
      },
      created() {
        Object.assign(this.$data,{
          profile:"This is a Vue App"
        })
        console.log(this.$data);
      },
    })
  </script>

以上代码中浏览器会抛出一个 “profile is not defined” 的一个错误,这是为什么呢。
这里的profile则是created钩子函数中被赋予data选项的,也就是说profile在实例创建完成后被绑定到组件上的,并没有把profile加入数据响应式系统中,所以Vue给出了一个错误提示。此时的profile只是一个普通的JS属性,而非被Vue观察的对象。

所以我在实际开发中,应将尽可能在实例中被观察的数据预先在data中声明,以任何浏览器所支持的原生API都无法将数据动态加入响应式系统,不过Vue针对这一需求,也提供了相应的机制。

开发者可以使用 $ set方法位data选项动态绑定数据,但其也无法挂载响应式数据到 $ data根节点上,不过,既然这些数据要绑定到 $ data上,何不在初始化时声明呢?

	target    目标对象 
    key       键名
    value     键值
    this.$set(target, key, value)

下面,将分别演示使用原生方法Object.assign 和 Vue.$set 为自建挂载响应式数据实例。

<div id="app">
    <p>{{title}}</p>
    <p>{{obj.profile}}</p>
    <button @click="toggle">toggle</button>
  </div>
  <script>
    const vue = new Vue({
      el:"#app",
      data() {
        return {
          title:'A Vue App',
          obj:{} //$set 不能用于根节点data上
        }
      },
      created() {
        Object.assign(this.obj,{
          profile : "This is a Vue App",
        })
        console.log("created",this.obj);
      },
      mounted() {
        Object.assign(this.obj,{
          profile : "This is a Vue Test App",
        })
        console.log("mounted",this.obj);
      },
      methods: {
        toggle(){
          Object.assign(this.obj,{
          profile : "This is a Vue App for test",
        })
        console.log("toggle",this.obj);
        }
      },

相比于之前的Object.assign的示例,这次的视图表现更显奇怪,Vue不仅没给出错误提示,还响应了在created钩子函数中所做的修改,为什么呢?

  • 在组件实例被创建(beforeCreated和created之间)时,obj对象作为data选项的属性存在于实例中拥有合法的地址。
  • 在created钩子函数中,profile挂载到obj对象上,obj.profile有undefined变为被赋予的值。由于obj.profile被赋值时,实例已经过了将数据加入响应式系统的阶段,所以obj.profile未被观察。又因为实例尚未和DOM节点绑定(beforeMount),所以此时修改profile依然可以影响之后的试图表现。
  • 在mounted钩子函数和click事件中,由于实例已经绑定到DOM节点上且profile不存在响应式系统中,所以此时修改profile试图没有发生变化。

在created中以$set的方式为对象绑定属性。

created() {
        this.$set(this.obj,'profile','This is a Vue App')
        console.log("created",this.obj);
      },

此时的profile被加入Vue响应式系统,当点击按钮时,视图发生变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值