编程语言
首页 > 编程语言> > javascript-为什么VueJS检测到此属性被添加到数组中的对象?

javascript-为什么VueJS检测到此属性被添加到数组中的对象?

作者:互联网

在下面的代码段中,我有两个Vue组件,每个组件都有一个包含两个对象的items数组.如果每个组件的模板的show属性为true,则将其设置为显示items数组的对象.数组中的第一个对象最初的显示值为true.第二个对象未设置显示值.

new Vue({
  el: '#ex1',
  data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
  mounted() {
    // 2nd item's show property setting is not detected here
    this.items[1].show = true; 
  }
})

new Vue({
  el: '#ex2',
  data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
  mounted() {
    // 2nd item's show property setting IS detected...
    this.items[1].show = true; 
    
    // ...when the 1st item's show property is set to false
    this.items[0].show = false; 
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="ex1">
  Example 1:
  <div v-if="items[0].show">{{ items[0] }}</div>
  <div v-if="items[1].show">{{ items[1] }}</div>
</div>

<div id="ex2">
  Example 2:
  <div v-if="items[0].show">{{ items[0] }}</div>
  <div v-if="items[1].show">{{ items[1] }}</div>
</div>

在第一个示例中,我将items数组中第二个对象的show属性设置为true. Vue未检测到预期的模板更改.

在第二个示例中,我将第二个对象的show属性设置为true,然后将第一个对象的show属性设置为false.在这种情况下,Vue确实会检测items数组的两个元素中的更改并相应地更新模板.考虑到Vue的Change Detection Caveats,我不希望这样.

这似乎是一个无害的错误(如果甚至可以视为错误),因此我不确定是否值得报告.但是,我想知道是否有人能够解释这种行为.在第二个示例中,Vue为什么检测到show属性添加到对象?

解决方法:

更改反应特性(显示第一个对象)将触发重新渲染. Vue忠实地呈现模板引用的对象的当前状态,其中包括第二个对象.

第二个对象的show属性仍然不是反应性的,对其的更改将不会更新Vue.只是触发第一个对象的反应性属性状态的更改即可触发更新.

换句话说,更改第二个对象的show属性(因为它是在事后添加的)将永远不会更新Vue,但是更改第一个对象的show属性将始终更新,并且更新将仅呈现Vue的当前状态.数组,无论如何添加.

我不会认为这是一个错误.

一种了解差异的简单方法是在更新后将阵列记录到控制台.您将看到没有观察到第二个对象的show属性,但该属性仍然存在.

编辑
我想根据评论稍作澄清.对第二个对象所做的更改出现在Vue中的原因是因为重新渲染了整个Vue,并且在Vue中直接引用了第二个对象.例如,如果您将值传递给组件,则不会重新渲染第二个对象.

这是一个示例,显示将值传递给组件时,第二个对象从不更新(因为组件管理渲染).

console.clear()
 
 Vue.component("item", {
  props: ["item"],
  template: `
    <div>Item Show: {{item.show}}</div>
  `
 })
 
 new Vue({
      el: '#ex2',
      data: () => ({ items: [{name: 'apple', show: true}, {name: 'banana'}] }),
      mounted() {
        // 2nd item's show property setting IS detected...
        this.items[1].show = true; 
        
        // ...when the 1st item's show property is set to false
        this.items[0].show = false; 
      }
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="ex2">
  This will show false, because that is the current state and this object's show
  property is reactive
  <item :item="items[0]"></item>
  <hr>
  This will not show *anything*, despite the current state of show=true
  because the object's show property is not reactive
  <item :item="items[1]"></item>
</div>

标签:vue-js,vuejs2,javascript
来源: https://codeday.me/bug/20191109/2012894.html