Vue + ElementUI 实现侧边菜单点击时加载一个动态菜单在横向位置

狂风中的少年 提交于 2020-12-09 00:59:06

传统的左侧菜单的操作方式,在进行比对操作时并不是一个好的体验,下面讲到的实现是左侧菜单每次点击都会动态加载一个动态的横向菜单,而非仅左侧菜单一个入口

以下以Element UI组件库的菜单举例(虽然现在在切换到iview).

  1. 菜单在点击时的@select

  2. 在vuex中定义一个用于存放横向导航数据的数组

    1. 以下为vuex中的数据
    const state = {
        //导航
        navigations: []
    }
    const mutations = {
        set_navigations(state, data){
            state.navigations = [...data]
        }
    }
    const actions = {
        async SET_NAVIGATIONS({commit}, data){
            return commit('set_navigations',data)
        }
    }
    const getters = {
        navigations: state => state.navigations
    }
    // 此处省略挂载到store对象中的操作
    
    1. Sidebar中需要如下可计算变量
    computed: {
        navigations(){
            return this.$store.getters.navigations
        }
    }
    
    1. 对组件中el-menu的@select进行回调
    <el-menu :router='true' :unique-opened='true' active-text-color='#ffd04b'
             background-color='transparent'
             :default-active='$route.path' text-color='#FFF' @select='selectMenu'>
    
    1. selectMenu回调函数处理逻辑,对vue入参的处理目的只是为了拿到菜单的名称,当然读者能用其它方法(如路由名称)能做到同样的事也行
    selectMenu(path,_,vue){
      const navigations = this.navigations
      for (let navigation of navigations){
        if (navigation.title === vue.$el.innerText){
          return
        }
      }
      this.$store.dispatch('SET_NAVIGATIONS', [
          ...navigations,
        {title: vue.$el.innerText, name: path}
      ])
    }
    
    1. 以上实现了向vuex中添加点击到的菜单的path到vuex中,哪么下面就是将这些数据进行横向展示
      1. 实现了一个简单组件
      <template>
        <el-tabs :value='$route.path' @tab-remove='handleRemove' @tab-click='handleClick'>
          <slot/>
        </el-tabs>
      </template>
      
      <script>
      export default {
        name: "TabQueue",
        data() {
          return {
            tabs: 24
          }
        },
        methods: {
          handleRemove(name) {
            this.$emit('tab-remove', name);
          },
          handleClick(tab, event) {
            this.$emit('tab-click', tab, event);
          }
        }
      }
      </script>
      
      <style scoped>
      
      /*整个队列所用的*/
      >>> .el-tabs__nav-next, .el-tabs__nav-prev, .el-tabs__nav-scroll {
        line-height: 40px !important;
      }
      
      /*整个队列所用的*/
      >>> .el-tabs__item {
        padding:0 20px!important;
      }
      </style>
      
      1. 使用上面定义的声明的组件
      <TabQueue  @tab-remove="removeTab" @tab-click='handleClick'>
        <el-tab-pane label='首页' name='/dashboard'/>
        <el-tab-pane
            v-for='(item) in navigations'
            :key='item.name'
            :label='item.title'
            :name='item.name' closable/>
      </TabQueue>
      
      computed: {
          navigations() {
            return this.$store.getters.navigations
          }
      }
      
      removeTab(path) {
        console.log(path)
        const navigations = this.navigations
        let index = -1;
        for (let i = 0; i < navigations.length; i++) {
          if (navigations[i].name === path) {
            index = i
            break
          }
        }
        if (index >= 0) {
          navigations.splice(index, 1)
        }
        this.$store.dispatch('SET_NAVIGATIONS', navigations)
        if (navigations.length === 0) {
          this.$router.push({path: '/dashboard'})
          return
        }
        this.$router.push({path: navigations[navigations.length - 1].name})
      }
      
      handleClick(object) {
        this.$router.push({path: object.name})
      },
      

后记

上述代码逻辑足以实现图示中点击侧边栏菜单后自动加载到横向菜单的功能,可以使系统使用者更简单操作,虽然逻辑实现了菜单的切换性便捷,但未在此实现接切换路由再切回来时数据恢复的问题,如果没有保存离开路由时保存现场再到切回路由时恢复现场的能力,哪么这个功能也就少了一半的灵魂.

举个例子: 在A路由的页面填写了一半的数据,忽然发现有个数据是B页面上某个数据,于是切换便捷菜单找到了数据,但再切回来时发现之前填写的一半数据已经丢了,所以保存/恢复现场的功能与本章功能是相辅相成的,以后有时间再补这个功能吧

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!