javascript - 为什么 Vue 在使用 unshift 时不更新 $ref 中的数组顺序?

标签 javascript vue.js

考虑以下示例:

<template>
  <div>
    <button @click="addItem">Add Item</button>
    <h1>Fruits</h1>
    <ul>
      <li
        v-for="(item, index) in items"
        ref="items"
        v-bind:key="item.id"
        @click="logIndex(index)"
      >
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Fruits",
  data() {
    return {
      items: [
        { name: "apple", id: 1 },
        { name: "banana", id: 2 },
      ],
    };
  },
  methods: {
    addItem() {
      const nextNumber = Math.max(...this.items.map((x) => x.id)) + 1;
      this.items.unshift({
        name: "peach " + nextNumber,
        id: nextNumber,
      });
      console.log(this.$refs);
      console.log(this.items);
    },
    logIndex(index) {
      console.log(index);
      console.log(this.items[index]);
      console.log(this.$refs.items[index]); //this seems reasonable to assume
      //using the index here would return
      //the correct reference, but maybe not
    },
  },
};
</script>

如果您查看控制台输出,您会发现 refs 和 items 的顺序不同。单击水果项目将记录该特定项目。您会注意到这些项目有所不同。为什么会这样呢?裁判的顺序是否因某种原因而不同?

这里有一个 CodeSandbox 来测试它 View example

一些背景:

我今天遇到了这个场景。举例来说,您有一个带有一系列子组件的组件。如果您需要访问同级组件,您可以从原始组件发出,处理父组件上的事件,然后从父组件访问另一个同级组件。我发现如果已添加原始数组,则传递索引并使用它根本不起作用。我能够通过使用 .find 并匹配组件数据来解决这个问题。

我确实意识到,在上述场景中使用 Vuex 或类似的方法可能是理想的,但我仍然想知道 this.$refs 是否不会反射(reflect)底层数据的排序顺序以及为什么这是这样所以。

任何解决方法的代码示例都会非常有帮助。

最佳答案

以下是基于 link 的解决方法的实际代码示例@Michal 提到的。

<template>
  <div>
    <button @click="addItem">Add Item</button>
    <h1>Fruits</h1>
    <ul>
      <li
        v-for="(item, index) in items"
        ref="items"
        v-bind:key="item.id"
        @click="logIndex(index)"
        :data-index="index"
      >
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Fruits",
  data() {
    return {
      items: [
        { name: "apple", id: 1 },
        { name: "banana", id: 2 },
      ],
    };
  },
  methods: {
    addItem() {
      const nextNumber = Math.max(...this.items.map((x) => x.id)) + 1;
      this.items.unshift({
        name: "peach " + nextNumber,
        id: nextNumber,
      });
      console.log(this.$refs);
      console.log(this.items);
    },
    logIndex(index) {
      console.log(index);
      console.log(this.items[index]);
      console.log(this.$refs.items.find(x => index === parseInt(x.dataset.index)));
    },
  },
};
</script>

这个想法是将索引或其他键存储为 DOM 属性,然后在需要 $ref 时查找它。并不理想,但这是建议作为解决方法的最佳想法。理想情况下,使用不涉及访问 $refs 的方法可能是最好的。

至于为什么会发生这种情况,由于性能原因,似乎无法保证顺序。 Vue 实际上只是 pushes the ref onto the array .

 refs[key].push(ref) 

关于javascript - 为什么 Vue 在使用 unshift 时不更新 $ref 中的数组顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64452826/

相关文章:

javascript - (Javascript) Console.log 输出对象的值并在下一行添加 undefined

javascript - 如何使用 Angular.js 和 UI Bootstrap 创建分页

javascript - 如何循环遍历数组并创建带有类别的术语表列表

javascript - vue.js 表格中的条件渲染

javascript - 时间序列流,删除 x 轴上的上午/下午和 24 小时格式

javascript - 每次使用 Vue js 时,WebComponents 都会重新初始化

javascript - 即使提及扩展名,Imacros.. 文件默认也会附加扩展名

javascript - 登录表单中密码验证区分大小写

Javascript/jQuery 插件到插件以更改边框颜色,相对于元素的背景颜色

html - 如何在 vue.js webpack 项目上正确设置 favicon.ico?