iview组件库:使用Menu组件时手风琴属性accordion失效的解决方案

发布于:2025-06-11 ⋅ 阅读:(34) ⋅ 点赞:(0)

1、需求导入

今天在修改Vue管理系统平台项目的左侧导航栏时发现,直接添加手风琴属性(即:最多只展开一个节点菜单)accordion时是没有反应的,查阅官网的API也没查不到具体是什么原因导致,下面是iview官网的api文档说明以及示例:
这是官网的示例代码:

<Col span="8">
            <Menu :theme="theme2" :open-names="['1']" accordion>
                <Submenu name="1">
                    <template slot="title">
                        <Icon type="ios-paper" />
                        内容管理
                    </template>
                    <MenuItem name="1-1">文章管理</MenuItem>
                    <MenuItem name="1-2">评论管理</MenuItem>
                    <MenuItem name="1-3">举报管理</MenuItem>
                </Submenu>
                <Submenu name="2">
                    <template slot="title">
                        <Icon type="ios-people" />
                        用户管理
                    </template>
                    <MenuItem name="2-1">新增用户</MenuItem>
                    <MenuItem name="2-2">活跃用户</MenuItem>
                </Submenu>
                <Submenu name="3">
                    <template slot="title">
                        <Icon type="ios-stats" />
                        统计分析
                    </template>
                    <MenuGroup title="使用">
                        <MenuItem name="3-1">新增和启动</MenuItem>
                        <MenuItem name="3-2">活跃分析</MenuItem>
                        <MenuItem name="3-3">时段分析</MenuItem>
                    </MenuGroup>
                    <MenuGroup title="留存">
                        <MenuItem name="3-4">用户留存</MenuItem>
                        <MenuItem name="3-5">流失用户</MenuItem>
                    </MenuGroup>
                </Submenu>
            </Menu>
        </Col>

这确实能够实现手风琴,但是我在这个基础上修改,调用的视图是从后台那边拿过来的时候,却意外的发现用不了了,代码如下:

<Menu
        class="menu-demo"
        accordion
        :active-name="$route.path"
        :theme="theme"
        v-for="item in list"
        :key="item.id"
      >
        <!-- 展开没有子菜单 -->
        <MenuItem
          v-if="!item.children || item.children.length == 0"
          :key="item.id"
          :name="item.url"
          :to="item.url"
        >
          <Icon :custom="item.src"></Icon>
          <!-- <Icon :type="item.src"></Icon> -->
          <span>{{ item.title }} </span>
        </MenuItem>
        <!-- 展开有子菜单 -->
        <Submenu :name="item.id" v-else>
          <template slot="title">
            <!-- <Icon :type="item.src"></Icon> -->
            <Icon :custom="item.src"></Icon>
            <!-- {{item.name}} -->
            <span>{{ item.title }} </span>
          </template>
          <MenuItem
            v-for="i in item.children"
            :key="i.id"
            :name="i.title"
            :to="i.url"
          >
            {{ i.title }}
          </MenuItem>
        </Submenu>
      </Menu>

2、解决途径

直接添加属性上去是没有任何反应的,中午翻阅了下资料,得知,最好不要直接遍历MenuItem元素,我就使用一个template去包裹它在循环处理,为什么使用template呢?因为template是不会在页面渲染时会有dom元素占位的,因为他编译后不会出现在元素的结构中去。
后来修改后的代码如下:

<Menu
        :accordion="true"
        :active-name="$router.path"
        router
        theme="light"
        ref="child"
        style="width: 200px"
      >
        <!-- 展示的数据视图列表 -->
        <template v-for="item in list">
          <template v-if="item.children && item.children.length > 0">
            <Submenu :name="item.id" :key="item.id">
              <template slot="title">
                <Icon :custom="item.src"></Icon>
                <span>{{ item.title }} </span>
              </template>
              <template v-for="child in item.children">
                <MenuItem :key="child.id" :name="child.title" :to="child.url">
                  {{ child.title }}</MenuItem
                >
              </template>
            </Submenu>
          </template>
          <template v-else>
            <MenuItem :key="item.id" :name="item.url" :to="item.url">
              <Icon :custom="item.src"></Icon>
              <!-- <Icon :type="item.src"></Icon> -->
              <span>{{ item.title }} </span>
            </MenuItem>
          </template>
        </template>
      </Menu>

经过处理后,手风琴效果便成功的展示了,但是中间有个问题,熟悉Vue的都知道,v-for需要绑定key,这样才能让虚拟DOM高效更新。问题就出在这里,如果试图给<template>绑定key,那么控制台就会报错,这是为什么呢?原因也正是key的优点导致的,key值的绑定便于dom高效更新,但是template在编译后会是不会在出现在渲染的结果中的,意思说白了就是编译完它就不存在了,那么你的key如果绑定在template上,它都不存在了还如何去让它去高效更新呢?解决方法是可以用将key值绑定在MenuItem上,这样就很好的避免了上述问题,同时,如果还有其他的需求也可以利用api的文档去修改,比如:我们想修改左侧导航栏的样式或者当点击某个导航栏的时候触发一些提醒或者什么的,都可以利用如下的api去实现:

iview官网api.png

3、展示结果

导航栏展示效果.gif
最后编辑于:2025-06-05 21:01:14


喜欢的朋友记得点赞、收藏、关注哦!!!