如何解决 vuetify 扩展面板的问题?

时间:2021-03-01 15:02:06

标签: javascript vue.js vuejs2 vuetify.js

上下文:

我目前正在开发一个使用 vuetify(Vuetify1.5) 扩展面板的复杂应用程序, 我需要根据展开的扩展面板来绑定/突出显示画布。 (在下面的演示中,我使用 v-chip 而不是 canvas 重新创建了相同的问题)。

为了实现上述目标,我遵循以下步骤。

S1:在 v-model 上计算得到扩展/用户扩展扩展面板索引

S2:将索引与项目索引匹配并突出显示元素。

注意事项:

1.不能使用项目索引作为扩展面板的键,因为它会降低性能,重新渲染整个扩展面板组件。 How to improve performance while using dynamic components in vue?

2.不能对面板 v-model 使用布尔数组,因为我需要索引来突出显示正确的 v-chip。

问题:

当我尝试将新元素添加/推送到扩展面板使用的 items 数组时,错误的画布/v-chip 被突出显示。

这似乎是一个现有问题,正在此处报告:https://github.com/vuetifyjs/vuetify/issues/11225

是否有解决此问题的方法?

new Vue({
  el: '#app',
  data() {
    return {
      panel: 0,
      items: [{
        name: "Three"
      }, {
        name: "Two"
      }, {
        name: "One"
      }],
      selectedIndex: 0
    }
  },
  methods: {
    addItem() {
      this.items.unshift({
        name: `Infinity ${this.items.length+1}`
      })
    }
  },
  watch: {
    panel(value) {
     // if (value) {
        this.selectedIndex = value;
   //   }
    }
  }
})
table {
  max-width: 80px;
  max-height: 68px;
  font-size: 10px;
  background-color: #ffd23f;
}
<link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">
<div id="app">
  <v-app id="inspire">
    <div>
      <v-layout>
        <v-flex>
          <table border="1">
            <tr>
              <th>Item Index</th>
              <th>Selected index</th>
              <th>Outline</th>
            </tr>
            <tr v-for="(item,i) in items">
              <td class="text-xs-center">{{i}}</td>
              <td class="text-xs-center">{{selectedIndex}}</td>
              <td class="text-xs-center">{{i!=selectedIndex}}</td>
            </tr>
          </table>
        </v-flex>
      </v-layout>
      <v-layout>
        <v-flex md4 xs4>
          <div class="d-flex justify-between align-center mb-3">
            <v-btn icon @click="addItem">
              <v-icon>add</v-icon>
            </v-btn>
          </div>

          <v-expansion-panel v-model="panel">
            <v-expansion-panel-content v-for="(item,i) in items" :key="item.name">
              <div slot="header">Item {{item.name}}</div>
              <v-card>
                <v-card-text>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</v-card-text>
              </v-card>
            </v-expansion-panel-content>
          </v-expansion-panel>
        </v-flex>
        <v-flex>
          <v-spacer class="my-4" />
          <div class="text-xs-center" v-for="(item,i) in items" :key="item.name">
            <v-chip :outline="i!=selectedIndex" color="secondary">{{item.name}}</v-chip>
          </div>
        </v-flex>
      </v-layout>

    </div>
  </v-app>
</div>

1 个答案:

答案 0 :(得分:1)

我认为这就是您想要做的。我做了一些小改动 - 我正在推送到 items 数组而不是 unshifting。如果您想将新项目保留在顶部,我建议您颠倒数组的顺序。我删除了观察者并为 setNewIndex 添加了一个新方法。我还在屏幕上的几个地方打印了 i 以便更容易理解。

new Vue({
  el: '#app',
  data() {
    return {
      panel: 0,
      items: [{
        name: "Three"
      }, {
        name: "Two"
      }, {
        name: "One"
      }],
      selectedIndex: 0
    }
  },
  methods: {
    addItem() {
    let added = this.items.length
      this.items.push({
        name: `Infinity ${added}`
      })
      console.log({added});
      this.setNewIndex(added)
    },
    setNewIndex(i){
    this.selectedIndex = i+"_selected";
    }
  },
  watch: {
    
  }
})
table {
  max-width: 80px;
  max-height: 68px;
  font-size: 10px;
  background-color: #ffd23f;
}
<link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">
<div id="app">
  <v-app id="inspire">
    <div>
      <v-layout>
        <v-flex>
          <table border="1">
            <tr>
              <th>Item Index</th>
              <th>Selected index</th>
              <th>Outline</th>
            </tr>
            <tr v-for="(item,i) in items">
              <td class="text-xs-center">{{i}}</td>
              <td class="text-xs-center">{{selectedIndex}}</td>
              <td class="text-xs-center">{{i+'_selected'!=selectedIndex}}</td>
            </tr>
          </table>
        </v-flex>
      </v-layout>
      <v-layout>
        <v-flex md4 xs4>
          <div class="d-flex justify-between align-center mb-3">
            <v-btn icon @click="addItem">
              <v-icon>add</v-icon>
            </v-btn>
          </div>

<pre>{{selectedIndex}}</pre>

          <v-expansion-panel v-model="panel">
            <v-expansion-panel-content v-for="(item,i) in items" :key="item.name" >
              <div slot="header" @click="setNewIndex(i)">Item {{i}} {{item.name}}</div>
              <v-card>
                <v-card-text>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</v-card-text>
              </v-card>
            </v-expansion-panel-content>
          </v-expansion-panel>
        </v-flex>
        <v-flex>
          <v-spacer class="my-4" />
          <div class="text-xs-center" v-for="(item,i) in items" :key="item.name">
            <v-chip :outline="i+'_selected' != selectedIndex" color="secondary">{{i}}{{item.name}}</v-chip>
          </div>
        </v-flex>
      </v-layout>

    </div>
  </v-app>
</div>