为什么在计算 属性 中引用 v-model 时 vuejs 会复制其 v-model 数据?

Why does vuejs replicates its v-model data when the v-model is referenced within a computed property?

在下面的代码中:

JS

const App = {
  template: '#app-template',
  data: () => ({
    selected: [],
    items: Array.from({length: 50}, (x, i) => i+1).map(i => ({
      id: i ,
      name: `Item ${i}`,
      subtitle: `Subtitle ${i}`
    }))
  }),
  computed: {
    parsedItems() {
      this.selected;
      return this.items.map(item => ({
        someValue: 3,
        ...item
      }));
    }
  }
}


new Vue({
  vuetify: new Vuetify(),
  render: h => h(App)
}).$mount('#app')

HTML

<script type="text/x-template" id="app-template">
  <v-app>
    {{selected}}
    <v-container>

        <v-virtual-scroll
          :items="parsedItems"
          :item-height="65"
          height="500"
        >
          <template v-slot="{ item, index }">
           <v-list-item-group
             v-model="selected"
             multiple
           >
            <v-list-item :key="item.id" :value="item">
              <v-list-item-action>
                <v-checkbox
                  :input-value="selected.includes(item.id)"
                  color="primary"
                />
              </v-list-item-action>
              <v-list-item-content>
                <v-list-item-title>
                  Index: {{ index }} {{ item.name }}
                </v-list-item-title>
                <v-list-item-subtitle>
                  {{ item.subtitle }}
                </v-list-item-subtitle>
              </v-list-item-content>
            </v-list-item>
           </v-list-item-group>
          </template>
        </v-virtual-scroll>
    </v-container>
  </v-app>
</script>

<div id="app"></div>

当我选中或取消选中其中一个复选框时 - selected v 模型总是添加另一个实例,尽管它之前已经包含一个实例。

删除 this.selected;(下面代码笔中的第 16 行)解决了这个问题。

我怀疑 this.selected 以某种方式取消引用它自己的值,然后无法验证之前选择的项目的外观。

这里有一个关于手头问题的 Codepen:https://codepen.io/MichaelKatz/pen/vYXXdgb

在我的真实场景中,我需要根据之前所做的选择(即删除/重新添加项目)过滤和操作列表中的项目。 我通过使用计算 item 属性 来实现它,它从先前选择的项目、selected v 模型中派生其内容,而我当前的解决方案将要求我 JSON.stringify我所有的对象,本质上是使它们成为基于值的字符串以保持检查状态。

在我看来,问题是您使用了 multiple 道具,这将允许多项选择。

      <template v-slot="{ item, index }">
       <v-list-item-group
         v-model="selected"
         multiple
       >

只需将其删除即可解决您的问题。

v-model 似乎不适用于对象

<v-list-item :key="item.id" :value="item">    <!-- change this -->
<v-list-item :key="item.id" :value="item.id"> <!-- into this   -->

并创建一个新的计算 属性 来“混合”这些 ID:

selectedItems() {
  return this.selected.map(id => this.parsedItems.find(x => x.id === id))
}

Updated Codepen

似乎在过滤它引用的项目时访问 v 模型,创建了其中对象的取消引用。

我能想到的最佳解决方案是添加一个额外的计算 属性,它将包含涉及 this.selected.

的逻辑

确实解决了我的问题

  computed: {
    parsedItems() {
      return this.items.map(item => ({
        someValue: 3,
        ...item
      }));
    },
    filteredItems() { // adding another computed property while using this.selected
      this.selected;
      return this.parsedItems;
    }
  }
}