ElemeFE / element

A Vue.js 2.0 UI Toolkit for Web
https://element.eleme.io/
MIT License
54.12k stars 14.64k forks source link

NavMenu使用了for渲染后,无法正常展开菜单 #2670

Closed arzcl closed 7 years ago

arzcl commented 7 years ago

NavMenu使用了for渲染,并启用了 :default-active="$route.path"后,发现在刷新页面的时候,能高亮却无法正确展开菜单


<el-menu :default-active="$route.path" class="el-menu-vertical-demo" :router="true">
                        <template v-for="(item, index) in columnArray">
                            <el-submenu v-if="item.route === 'nav'" :index="index + ''">
                                <template slot="title">
                                    <i :class="item.icon "></i>{{ item.name }}
                                </template>
                                <el-menu-item v-for="tree in item.column" :index="tree.route">
                                    {{ tree.name }}
                                </el-menu-item>
                            </el-submenu>
                            <el-menu-item v-else :index="item.route">
                                <i :class="item.icon"></i>{{ item.name }}
                            </el-menu-item>
                        </template>
                    </el-menu>
erguotou520 commented 7 years ago

能先格式化下你的代码么 用3个斜点

arzcl commented 7 years ago

@erguotou520 已经格式好了,重新帮忙看下,感谢~


<el-menu :default-active="$route.path" class="el-menu-vertical-demo">
       <template v-for="(item, keys) in columnArray">
             <template v-if="item.route === 'nav'">
                  <el-submenu :index="keys + ''">
                       <template slot="title">
                           <i :class="item.icon "></i>{{ item.name }}
                        </template>
                        <template v-for="tree in item.column">
                              <router-link :to="tree.route">
                                   <el-menu-item :index="tree.route">
                                        {{ tree.name }}
                                   </el-menu-item>
                               </router-link>
                            </template>
                      </el-submenu>
                 </template>
                  <template v-else>
                        <router-link :to="item.route">
                            <el-menu-item :index="item.route">
                                   <i :class="item.icon"></i>{{ item.name }}
                            </el-menu-item>
                        </router-link>
                     </template>
         </template>
</el-menu>
erguotou520 commented 7 years ago

既然用了el-menu-item的index做路由跳转 应该就不要用router-link了,至于为什么没展开就不是很清楚了

arzcl commented 7 years ago

@erguotou520 设置了default-openeds="[2]"之后,的确能默认展开,但是却无法点击关闭,看了这个issue:https://github.com/ElemeFE/element/issues/2279 用:default-openeds="[2]" 却无法默认展开,在官网文档也没找到default-openeds的用法教程,,

erguotou520 commented 7 years ago

刚那条评论删了,因为我发现我的系统也没设置default-openeds就可以自动展开

arzcl commented 7 years ago

@erguotou520 好吧,那只能先这样了,非常感谢您的热心帮助!

arzcl commented 7 years ago

@erguotou520 对的,这个router-link是多余的,删掉了~

erguotou520 commented 7 years ago

还有,不需要template来辅助,直接在el-submenuel-menu-itemv-if是可以的

arzcl commented 7 years ago

@erguotou520 的确可以,一下子就简洁多了,刚刚接触vue,不太熟悉,真的感谢

erguotou520 commented 7 years ago

如果就按照正常的来,应该是可以自动展开的,你重新试下,如果可以的话就关了issue

arzcl commented 7 years ago

@erguotou520 还是不能正常展开,只能高亮


<el-menu :default-active="$route.path" class="el-menu-vertical-demo" :router="true">
                        <template v-for="(item, index) in columnArray">
                            <el-submenu v-if="item.route === 'nav'" :index="index + ''">
                                <template slot="title">
                                    <i :class="item.icon "></i>{{ item.name }}
                                </template>
                                <el-menu-item v-for="tree in item.column" :index="tree.route">
                                    {{ tree.name }}
                                </el-menu-item>
                            </el-submenu>
                            <el-menu-item v-else :index="item.route">
                                <i :class="item.icon"></i>{{ item.name }}
                            </el-menu-item>
                        </template>
                    </el-menu>
您那边用for渲染能正常展开吗?不知道是不是我用法有问题,,,
erguotou520 commented 7 years ago

我的是可以的,至于你的为什么不行,得问他们开发的了

arzcl commented 7 years ago

@erguotou520 那可以麻烦您把这段菜单渲染发上来看看么,,我比对参照下

erguotou520 commented 7 years ago
<el-menu :default-active="$route.path" theme="dark" :router="true">
  <el-menu-item index="/subsystems"><i class="iconfont icon-system"></i>{{$t('menu.subsystem')}}</el-menu-item>
  <el-submenu index="/workflow">
    <template slot="title"><i class="iconfont icon-process"></i>{{$t('menu.flow')}}</template>
    <el-menu-item index="/flow/workflows"><i class="iconfont icon-template"></i>{{$t('menu.workflows')}}</el-menu-item>
    <el-menu-item index="/flow/my"><i class="iconfont icon-flow"></i>{{$t('menu.myFlow')}}</el-menu-item>
  </el-submenu>
  <el-submenu index="/base">
    <template slot="title"><i class="el-icon-information"></i>{{$t('menu.base')}}</template>
    <el-menu-item index="/base/departments"><i class="iconfont icon-cluster"></i>{{$t('menu.departments')}}</el-menu-item>
    <el-menu-item index="/base/users"><i class="iconfont icon-users"></i>{{$t('menu.users')}}</el-menu-item>
    <el-menu-item index="/base/roles"><i class="iconfont icon-roles"></i>{{$t('menu.roles')}}</el-menu-item>
  </el-submenu>
</el-menu>
arzcl commented 7 years ago

@erguotou520 我刚刚开始就是这样手动写的,是没问题,但是全部用for渲染就无效

erguotou520 commented 7 years ago

这就不是很清楚了

arzcl commented 7 years ago

@erguotou520 嗯嗯,非常感谢您的帮助

forzalianjunting commented 7 years ago

我也遇见了同样的问题,刷新的时候,如果全部是手写的菜单,menu-item高亮的时候,对应的submenu就会展开;但如果是通过v-for渲染的,则menu-item高亮,但对应的submenu并不会展开

ckken commented 7 years ago

遇到同样问题无解

uojo commented 7 years ago

遇到同样的问题,无解,用for 循环 传入的 index ,只能高亮,不能自动展开

my9074 commented 7 years ago

同上,用for 循环 传入的 index ,只能高亮,不能自动展开。感觉 default-openeds 属性支持的不是特别友好

baimiaolei commented 7 years ago

同上,用for循环 不能自动展开 无解

kouguopeng commented 7 years ago

我的可以 image 感觉是你数据结构的问题

reverland commented 7 years ago

我好像因为动态生成menu内容遇到类似的问题了,可能你们的遍历数据开始是空的? 暂时用了一些奇怪的workaround来避免这个问题

arzcl commented 7 years ago

@reverland 感觉应该是这个原因导致的,今晚回去测试下,如果是的话,那可以用localStorage/sessionStorage 进行菜单数据缓存

reverland commented 7 years ago

@arzcl https://github.com/ElemeFE/element/pull/3671

Ppsj commented 7 years ago

@erguotou520 你代码段的 $t 是什么。。求指教

Property or method "$t" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. 
erguotou520 commented 7 years ago

@Ppsj 国际化啊

baiyaaaaa commented 7 years ago

导致这个问题是因为你的数据是异步的,那么在这种情况下你应该在数据来的时候设置一次 default-openeds 。

arzcl commented 7 years ago

利用 NavMenu 组件的 default-openeds +select 事件 + sessionStorage 基本实现了我的需求,代码如下:

    这个是写在组件创建完后获取数据的方法里的
    // 每次载入路由的时候,都利用 sessionStorage 取值对 NavMenu  做展开处理
    if (sessionStorage.getItem('defaultOpeneds') !== null) {
          self.defaultOpeneds = [sessionStorage.getItem('defaultOpeneds')]
     }

select 事件

    handleSelect (key, keyPath) {
         // 利用 sessionStorage 储存当前点击的菜单组
        sessionStorage.setItem('defaultOpeneds', keyPath[0])
    }

如果有更好的方法,烦请告知下我,感谢!

prettyGirlH commented 7 years ago

@kouguopeng ,你的information数组中的数据,是不是直接写在data中的?

baijunjie commented 7 years ago

我是这样使一级菜单全部默认打开的

  <el-menu :default-active="$route.fullPath"
             :default-openeds="links.map(item => item.path)"
             router>
        <template v-for="(link, index) in links"
                  v-if="!link.hide && link.path">
            <el-submenu v-if="link.children && link.children.length"
                        :key="link.path"
                        :index="link.path">

                <template v-if="link.empty"
                          slot="title"
                          class="submenu-title">
                    <i :class="link.icon"></i>
                    <span v-text="$t(link.i18n)"></span>
                </template>
                <el-menu-item v-else
                              slot="title"
                              class="submenu-title"
                              :index="link.path">
                    <i :class="link.icon"></i>
                    <span v-text="$t(link.i18n)"></span>
                </el-menu-item>

                <el-menu-item v-for="(childLink, childIndex) in link.children"
                              v-if="!childLink.hide && childLink.path"
                              :key="childLink.path"
                              :index="childLink.path">
                    <i :class="childLink.icon"></i>
                    <span v-text="$t(childLink.i18n)"></span>
                </el-menu-item>
            </el-submenu>

            <el-menu-item v-else
                          :key="link.path"
                          :index="link.path">
                <i :class="link.icon"></i>
                <span v-text="$t(link.i18n)"></span>
            </el-menu-item>

        </template>
    </el-menu>
Jason19901023 commented 7 years ago

既然是异步获取菜单数据的原因,那么就在el-menu组件上面加上v-if指令进行判断就行。 比如可以设置menuList初始化为一个空数组,在el-menu组件上加上v-if="menuList.length>0"的判断,等菜单数据通过异步请求获取到的时候,el-menu组件就会进行渲染,这样子,设置了default-active也可以就可以正常高亮并展开菜单了。 我写了个简单的例子:https://jsfiddle.net/w340e5w9/1/

K-walker commented 6 years ago

@kouguopeng 我很想问一下,通过for去动态渲染菜单,一般我们的菜单数据都是树形结构的,不用递归的话,怎么能够一层一层往下渲染呢,我看你贴的代码,知道了第二层级,如果第二层级下面还有children你怎么渲染出来呢,你这样只能渲染出2层的菜单啊

Ruloce commented 6 months ago

既然是异步获取菜单数据的原因,那么就在el-menu组件上面加上v-if指令进行判断就行。 比如可以设置menuList初始化为一个空数组,在el-menu组件上加上v-if="menuList.length>0"的判断,等菜单数据通过异步请求获取到的时候,el-menu组件就会进行渲染,这样子,设置了default-active也可以就可以正常高亮并展开菜单了。 我写了个简单的例子:https://jsfiddle.net/w340e5w9/1/

这是有用的,感谢帮助