Vue.js似乎在变量改变时没有更新DOM

3
我相信这是一个非常简单的问题,但我已经花了大约3个小时来尝试解决它,但无济于事。如果我在Vue对象中绑定一个变量,例如data:{x:a},其中a是某个变量,然后我改变a的值,我认为它会改变data.x的值,不是吗?
我目前正在尝试使用v-if/v-else链,其中if语句涉及不等式,但即使在它应该评估为true之后,显示的内容也没有改变。我编写了一些示例代码,并附带了一个JSFiddle。
<div id="app">
  <button v-if="unlocked">
    Unlocked
  </button>
  <button v-else-if="a >= b">
    Available
  </button>
  <button v-else>
    Unavailable
  </button>
  <span>{{a}}</span>
</div>

而且JS:

var x = {
    unlocked: false,
  a: 0,
  b: 10,
}

new Vue({
  el: "#app",
  data: {
    unlocked: x.unlocked,
    a: x.a,
    b: x.b
  },
});

function y() {
    x.a++;
  console.log(x.a);
}

var z = setInterval(y, 250);

https://jsfiddle.net/ny5phzqe/

它增加了变量,但文本和显示的按钮都没有改变。我对Vue有基本的误解吗?
3个回答

3
如果我在Vue对象内部绑定一个变量,例如data: {x: a},其中a是某个变量,然后我改变a的值,我认为它会同时改变data.x的值,但事实上并不是这样。造成这种误解的原因与Vue无关,而是与Javascript和对象引用的工作方式有关。简而言之,只有在a是对象时才是正确的,在您的示例中它是原始Number类型。
为什么这很重要?因为在Javascript中,当一个变量持有一个对象时,它实际上只包含对该对象的引用。但当一个变量持有一个原始类型时,它包含实际值。这意味着多个变量可以持有指向同一对象的引用。
如果a是一个对象,那么由于Javascript对象引用的本质,设置{x: a}意味着x和a都存储对同一对象的引用。你可以想象这个对象不属于x或a,它们都存储了对它的引用。如果您之后从x或a更改此对象的属性,这将反映在两个位置上。
但由于a是一个Number,所以由于Javascript原始类型的本质,设置{x: a}意味着x接收a的当前值的副本。没有引用,没有连接。它们立即包含完全独立的原始值。

1
这让我恍然大悟,非常感谢!我应该只需设置 data: {x: x},是吗?或者这是不好的做法? - Makaires
欢迎 :) 关于最佳实践: 请注意x是在替换组件的数据对象,而z则是替换了一个事件处理程序,这都是在组件外部进行的。请查看此jsfiddle链接以了解如何正确执行。 - Dan
对于我的实际项目,许多其他函数能够添加到 fiddle 中等同于 x.a 的内容,并且将有多个“组”需要依赖于 x.a 的变化。我是否希望在变量更改时简单地包含一种方法来同时更改每个依赖的 Vue 对象?还是将其设置为对象会更好呢? - Makaires
每当某个东西依赖于组件“数据”的更改时,通常需要使用“计算属性”。如果您想将一个粗略的小提琴与一个错误的示例链接起来,我可以尝试进行更正。 - Dan
当然,我会感激不尽!再次感谢您的所有帮助。 - Makaires
显示剩余8条评论

2
回答是肯定的和否定的。Vue会监视data.a,并直接更新它,但您正在更改x.a并期望data.a进行更新。这是行不通的。
您的代码流大致如下:
  1. 创建对象X
  2. 创建Vue实例
  3. 使用值x.a(0)初始化具有数据属性a的Vue实例
  4. 定义一个增量函数,该函数会增加x.a
  5. 调用增量函数(操作x)
data.a和x之间没有“连接”或反应性。Vue将根据data.a的变化更新视图/模板,但您从未更改该值。您正在更改x.a
以下是如何更改data.a的工作示例。
new Vue({
      el: "#app",
      data: {
        unlocked: false,
        a: 0,
        b: 10
      },
      methods: {
        increment() {    
            this.a++;
            console.log(x.a);
        }    
      },
      mounted() {
        setInterval(this.increment, 1000)
        }
    });

请查看这个代码片段 https://jsfiddle.net/m46sa3og/1/

最初的回答:


1
当您声明时:

a: x.a

你正在分配一个初始值。
如果你想更新这个值,你需要在Vue对象内部的变量上进行更改。最佳实践是在组件内使用一个方法:
var myVue = new Vue({
  el: "#app",
  data: {
    unlocked: false,
    a: 0,
    b: 10
  },
  methods: {
     increment() {
        this.a++
        console.log(this.a)
     }
  }
});
myVue.increment()
console.log(myVue.a)

哦!我想我可能是某种方式可怕地误读了其中一页。其中一部分,我认为如果您更改原始变量,则也会更改Vue对象中的变量,反之亦然。特别是这个部分。谢谢您的澄清! - Makaires

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接