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

标签 javascript vue.js vuejs2

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

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 属性?

最佳答案

更改reactive 属性(第一个对象的show)会触发重新渲染。 Vue 忠实地呈现模板引用的对象的当前状态,其中包括第二个对象。

第二个对象的 show 属性仍然不是响应式的,对它的更改不会更新 Vue。这只是触发更新的第一个对象上响应式属性状态的更改。

换句话说,改变第二个对象的 show 属性,因为它是在事实之后添加的,永远不会更新 Vue,但是改变第一个对象的 show 属性总是会更新,更新只会渲染数组的当前状态,无论它是如何添加的。

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

查看差异的一种简单方法是在更新后将数组记录到控制台。您会看到第二个对象的 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>

关于javascript - 为什么 VueJS 检测到这个属性被添加到数组中的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48811472/

相关文章:

javascript - 为什么我的页面上的事件选项卡没有变化?

javascript - 使用 Nuxt JS 进行 Vuetify js 优化

vue.js - 如何禁用 Vue 转换组等待浏览器选项卡被选择?

在 WebStorm 中调试 Vue.js 2

javascript - 将两个数组组合成选项数组

javascript - 单击链接时删除 Div

Javascript:列出文件和文件夹结构

javascript - Vue.js 3 - 在 vue 中使用 Vue I18n 插件时出错 - 无法设置未定义的属性 '_vm'

javascript - 如何让 Vue.js 对动态添加的数组属性的更改使用react?

arrays - 如何在 Vuex Store 中管理嵌套数组并通过组件传递它