LoginSignup
5
5

More than 5 years have passed since last update.

ElementUIのNavMenuをv-forで描画

Last updated at Posted at 2017-09-17

概要

ElementUIのNavMenuのサイドバー(グループ有り)をv-forで配列を元に生成します。

その際に若干ハマったので備忘録としても記載します。

ソース

コンポーネントの場合を想定しています。

template

template
<template>
  <el-menu mode="vertical" default-active="0">
    <el-menu-item-group v-for="(group, index1) in groups" :title="group.title">
      <el-menu-item v-for="(item, index2) in group.items" :index="getIndex()">
        {{ item.label }}
        {{ index }}
      </el-menu-item>
    </el-menu-item-group>
  </el-menu>
</template>

script

script
<script>
export default {
  data() {
    return {
      index: 0,
      groups: [
        { title: 'TITLE1',
          items: [
            { label: 'ITEM1' },
            { label: 'ITEM2' },
          ]
        },
        { title: 'TITLE2',
          items: [
            { label: 'ITEM3' },
            { label: 'ITEM4' },
            { label: 'ITEM5' },
          ]
        },
        { title: 'TITLE3',
          items: [
            { label: 'ITEM6' },
            { label: 'ITEM7' },
            { label: 'ITEM8' },
          ]
        }
      ]
    }
  },
  methods: {
    getIndex() {
      return String(this.index++)
    }
  }
}
</script>

画面イメージ

Kobito.xYzidJ.png

解説

<el-menu-item>のindexは、選択状態を制御するため、<el-menu>内では一般的に一意になる必要があります。
全体のアイテム数を取得するため、getIndex()という関数の中で、indexプロパティをインクリメントして返すようにしました。

レンダリング時にエラー

しかし、上記の方法だとコンソールにエラーログが吐かれてしまいます。

Kobito.MoagBY.png

[Vue warn]: You may have an infinite update loop in a component render function.

と出ていますが、なんのことかさっぱりわかりません。

解決策

どうやらインクリメントが悪さをしていたようです。
というか、インクリメントではなく、this.itemIndex += 1でもエラーは出ます。
原因はわかりませんが、v-forの処理の中で、dataプロパティの値を変更するのはNGのようです。。
※ 根本の原因はわかりませんでした。誰かお分かりでしたら教えて頂けると幸いです!

修正コード

template

template
<template>
  <el-menu mode="vertical" default-active="0">
    <el-menu-item-group v-for="(group, index1) in groups"
        :key="group.title" :title="group.title">
      <el-menu-item v-for="(item, index2) in group.items"
          :key="item.label" :index="getIndex(groups, index1, index2)">
        {{ item.label }}
        {{ getIndex(groups, index1, index2) }}
      </el-menu-item>
    </el-menu-item-group>
  </el-menu>
</template>

script

script
<script>
export default {
  data() {
    return {
      // index: 0, <-不要
      groups: [
        { title: 'TITLE1',
          items: [
            { label: 'ITEM1' },
            { label: 'ITEM2' },
          ]
        },
        { title: 'TITLE2',
          items: [
            { label: 'ITEM3' },
            { label: 'ITEM4' },
            { label: 'ITEM5' },
          ]
        },
        { title: 'TITLE3',
          items: [
            { label: 'ITEM6' },
            { label: 'ITEM7' },
            { label: 'ITEM8' },
          ]
        }
      ]
    }
  },
  methods: {
    getIndex(groups, groupIdx, itemIdx) {
      let total = 0
      for (var i = groupIdx - 1; i >= 0; i--) {
        total += groups[i].items.length
      }
      total += itemIdx
      return String(total)
    }
  }
}
</script>

  • data.indexは使用できなかったので、不要のため削除します。
  • methods.getIndexに、v-forとネストv-forの引数を3つ設定し、それらでアイテムの通し番号を計算します。

あんまりテストしていませんが、これで通し番号も取得でき、エラーも回避できたはずです。

ちなみに、String型で返却している理由は、<el-menu-item>indexプロパティがString型しか許容していないためです。

以上。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5