Vuetify扩展面板,打开状态不跟随dataprovider

Vuetify expansion panel, open state does not follow dataprovider

当数据数组改变顺序时,打开的面板的状态不会跟随它们的数据位置。

<div id="app">
  <v-app id="inspire">
    <div>
      <div class="text-center d-flex pb-4">
        <v-btn @click="changeOrder">Change order</v-btn>
        <v-btn @click="removeItem">Remove item</v-btn>
      </div>

      <v-expansion-panels
        v-model="panel"
        multiple
      >
        <v-expansion-panel
          v-for="(item, i) in items">
          <v-expansion-panel-header>{{ item.name }}</v-expansion-panel-header>
          <v-expansion-panel-content>
            Lorem ipsum dolor sit amet.
          </v-expansion-panel-content>
        </v-expansion-panel>
      </v-expansion-panels>
    </div>
  </v-app>
</div>

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
      panel: [],
      items: [
        { id:1, name: 'James', },
        { id:2, name: 'Bernt', },
        { id:3, name: 'Julie', },
        { id:4, name: 'Veronica', },
      ],
    }
  },
  methods: {

    changeOrder () {
      this.items = this.items.reverse();
    },

    removeItem () {
      this.items.splice(0, 1);
    },
  },
})

https://codepen.io/Agint/pen/GRpmBxE

在演示中,打开一个面板并单击按钮,您就会看到问题所在。从列表中删除数据时也会出现同样的问题。如果您打开了一个面板,然后将其取下,兄弟会突然打开。

如何解决这个问题?

根据 the docs v-expansion-panels 组件的 value 属性:

Controls the opened/closed state of content in the expansion-panel. Corresponds to a zero-based index of the currently opened content. If the multiple prop (previously expand in 1.5.x) is used then it is an array of numbers where each entry corresponds to the index of the opened content. The index order is not relevant.

这意味着打开的面板与其内容无关。如果反转或更改 items 数组的顺序,您还需要更新面板数组以相应地调整开放索引:

methods: {
    changeOrder () {
      // reverse the elements in your items array
      this.items = this.items.reverse()
      // get the max index of elements in your items array
      const maxIndex = this.items.length - 1
      // set index of each open panel to its inverse
      this.panel = this.panel.map(p => maxIndex - p)
    },
    removeItem () {
      this.items.splice(0, 1)
      // since the index of each item will be effectively reduced by 1
      // 
      this.panel = this.panel.map(p => p - 1)
    },
}