概要
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>
画面イメージ
解説
<el-menu-item>
のindexは、選択状態を制御するため、<el-menu>
内では一般的に一意になる必要があります。
全体のアイテム数を取得するため、getIndex()
という関数の中で、index
プロパティをインクリメントして返すようにしました。
レンダリング時にエラー
しかし、上記の方法だとコンソールにエラーログが吐かれてしまいます。
[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型しか許容していないためです。
以上。