一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - vue.js - vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

2022-03-08 16:53是日前端 vue.js

這篇文章主要介紹了vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

早就實現了功能,但是發現點擊的時候,選中的菜單項背景色會變白,周五時候仔細觀察了一下,發現并不是調整樣式的問題,而是選項沒有被選中,于是好好研究了一下組件遞歸這塊,總結記錄一下心路歷程

一、概念

遞歸:遞歸其實說白了,就是自己調用自己,樣子就像是套娃一個套一個的,小時候玩過一個游戲漢諾塔就是利用的遞歸原理:

vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

函數遞歸:函數利用函數名還調用自己
組件遞歸:所以組件遞歸利用的是vue組件中的name屬性來實現的

二、需求

實現可折疊動態渲染多級側邊欄導航

三、分析

vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

1、觀察到側邊欄導航是一級一級的,第二級就相當于再重復一遍第一級 2、有一個特點,有的菜單有下級,有的沒有下一級 3、動態渲染,說明是從后臺接口獲取的樹類型數據,動態的渲染上去 四、代碼實現 1、首先先執行一下文檔里的demo試一下:

文檔:element文檔

2、改成自己需要的樣式,第一次是這么寫的

父組件SideBar

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<template>
  <el-menu class="menu-wrap" :default-active="menuActiveName || 'home'" :active="menuActiveName || 'home'"
           :collapse="sidebarFold" :collapseTransition="false" :unique-opened="true" @select="selectItem">
    <template>
      <el-menu-item @click="sidebarFold = !sidebarFold">
        <i v-show="!sidebarFold" class="el-icon-s-fold"></i>
        <i v-show="sidebarFold" class="el-icon-s-unfold"></i>
        <span slot="title" class="sidebar-one">導航列表</span>
      </el-menu-item>
    </template>
<!--    <side-bar-item :list="menuList"></side-bar-item>-->
    <template v-for="(item,index) in menuList" class="menu">
      <!-- 標題 -->
      <template v-if="item.children.length" >
        <el-submenu :key="index" :index="item.id" class="sub-menu-item">
          <template :index="item.index" slot="title">
            <!--            <i :class="item.icon"></i>-->
            <i class="iconfont icon-danganjianying"></i>
            <span>{{item.name}}</span>
          </template>
          <el-menu-item-group class="menu-item-group">
            <side-bar-item :list="item.children"></side-bar-item>
          </el-menu-item-group>
        </el-submenu>
      </template>
      <!-- 選項 -->
      <template v-else>
        <el-menu-item :key="index" :index="item.id" class="menu-item">
          <!--          <i :class="item.icon"></i>-->
          <i class="iconfont icon-danganjianying"></i>
          <span>{{item.name}}</span>
        </el-menu-item>
      </template>
    </template>
  </el-menu>
</template>
 
<script>
 
export default {
  name: 'SideBar',
  components: {
    SideBarItem: () => import('@/components/common/SideBarItem')
  },
  data () {
    return {
 
    }
  },
  mounted () {
  },
  methods: {
    selectItem(name, path){
      // alert(name)
      this.$router.push(path)
      this.$store.commit('common/updateMenuActiveName', name)
    }
  },
  computed: {
    menuList: {
      get () {
        return this.$store.state.common.menuList
      },
      set (val) {
        this.$store.commit('common/updateMenuList', val)
      }
    },
    menuActiveName: {
      get () { return this.$store.state.common.menuActiveName },
      set (val) { this.$store.commit('common/updateMenuActiveName', val) }
    },
    sidebarFold: {
      get() {return this.$store.state.common.sidebarFold;},
      set(val) {this.$store.commit("common/updateSidebarFold", val);}
    },
  },
}
</script>
<style lang="less" scoped>
.menu-wrap{
  width: 200px;
  min-height: 1020px;
  background: url('../../assets/img/sidebar_bg.png') no-repeat;
  background-size: 100% 100%;
}
 
/deep/ .el-menu{
  background-color: transparent !important;
  .iconfont {
    font-size: 18px;
    vertical-align: sub;
    margin-right: 5px;
    display: inline-block;
    width: 20px;
    text-align: center;
  }
}
 
/deep/ .el-menu-item,
/deep/ .el-submenu__title{
  color: #fff;
 
  .iconfont{
    color: #fff;
  }
}
 
/deep/ .el-menu-item span,
/deep/ .el-submenu__title span{
  padding-left: 10px;
}
 
/deep/ .el-menu-item.is-active {
  -webkit-box-shadow: inset 5px 100px 0px -2px #0064B6;
  box-shadow: inset 5px 100px 0px -2px #0064B6;
}
 
/deep/ .el-submenu__title:hover,
/deep/ .el-menu-item:hover{
  background: #0064B6;
}
 
/deep/ .el-menu-item-group__title{
  padding: 0;
}
 
</style>

子組件SideBarItem

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<template>
  <div class="menu">
    <template v-for="(item,index) in list">
      <!-- 標題 -->
      <template v-if="item.children.length" >
        <el-submenu :key="index" :index="item.id" class="sub-menu-item">
          <template :index="item.index" slot="title">
<!--            <i :class="item.icon"></i>-->
            <i class="iconfont icon-danganjianying"></i>
            <span>{{item.name}}</span>
          </template>
          <el-menu-item-group class="menu-item-group">
            <side-bar-item :list="item.children"></side-bar-item>
          </el-menu-item-group>
        </el-submenu>
      </template>
      <!-- 選項 -->
      <template v-else>
        <el-menu-item :key="index" :index="item.id" class="menu-item" @click="selectItem(item.name, item.path)">
<!--          <i :class="item.icon"></i>-->
          <i class="iconfont icon-danganjianying"></i>
          <span>{{item.name}}</span>
        </el-menu-item>
      </template>
    </template>
  </div>
</template>
<script>
 
export default {
  name: 'SideBarItem',
  // props: ['list'],
  props: {
    list: {
      type: Array || ''
    }
  },
  data () {
    return {
      treeData: [{
        label: '某某省',
        children: [{
          label: '中共某某省委員會'
          // children: [{
          // label: '三級 1-1-1'
          // }]
        }, {
          label: '中共某某省辦公室'
        }, {
          label: '中共某某省組織部'
        }
        ]
      }
      ],
      isShow: false
      // menuList: []
    }
  },
  mounted () {
    this.loadSysMenu()
  },
  methods: {
    loadSysMenu () {
      // console.log('menu', this.menuList)
    },
    // personManage (name) {
    //   if (name === '人員管理') {
    //     this.isShow = !this.$store.state.common.rbflag
    //     // alert('111' + this.isShow)
    //     this.$store.commit('common/updateShowRbox', this.isShow)
    //   }
    // },
    selectItem(name, path){
      // alert(name)
      this.$router.push(path)
      this.$store.commit('common/updateMenuActiveName', name)
    }
  },
}
</script>
<style lang="less" scoped>
.menu{
  width: 100%;
 
  .sub-menu-item /deep/ .el-submenu__title,
  .menu-item{
    height: 60px;
    line-height: 60px;
    text-align: left;
    //padding-left: 30px !important;
    //border-bottom: 1px solid #000;
    //border-right: 1px solid #000;
    color: #fff;
  }
 
  .sub-menu-item .el-menu-item{
    padding-right: 0;
  }
 
 /deep/ .el-menu-item .is-active{
    background-color: #0087df;
  }
 
  .menu-item:hover,
  /deep/ .el-submenu__title:hover{
    background-color: #0087df;
  }
 
  .menu-item span,
  .sub-menu-item /deep/ .el-submenu__title>span{
    font-weight: 700;
  }
 
  .menu-item-group /deep/ .el-menu-item-group__title{
    padding: 0 !important;
  }
 
  .menu-item-group .menu-item{
    background: url('../../assets/img/sidebar_bg.png') no-repeat;
  }
 
  .el-menu-item-group span{
    font-weight: normal;
  }
 
}
 
</style>

后來發現折疊不成功,而且選中之后選中項樣式沒變,后來發現是沒選中,研究發現是因為多嵌套了一層div,而且用了el-menu-item-group項目中并不需要這個,于是改進如下:

父組件SideBar

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<template>
  <el-menu class="menu-wrap" :default-active="menuActiveName" :collapse="sidebarFold" :collapseTransition="false" :unique-opened="true">
    <template>
      <el-menu-item @click="foldSideBar">
        <i v-show="!sidebarFold" class="el-icon-s-fold"></i>
        <i v-show="sidebarFold" class="el-icon-s-unfold"></i>
        <span slot="title" class="sidebar-one">導航列表</span>
      </el-menu-item>
    </template>
    <side-bar-item v-for="menu in menuList" :key="menu.id" :menu="menu"></side-bar-item>
  </el-menu>
</template>
 
<script>
 
export default {
  name: 'SideBar',
  components: {
    SideBarItem: () => import('@/components/common/SideBarItem')
  },
  data () {
    return {
    }
  },
  mounted () {
  },
  methods: {
    foldSideBar(){
      this.sidebarFold = !this.sidebarFold
      this.menuActiveName = 'NAV'
    }
  },
  computed: {
    menuList: {
      get () {
        return this.$store.state.common.menuList
      },
      set (val) {
        this.$store.commit('common/updateMenuList', val)
      }
    },
    menuActiveName: {
      get () {
        console.log(this.$store.state.common.menuActiveName)
        return this.$store.state.common.menuActiveName
      },
      set (val) {
        this.$store.commit('common/updateMenuActiveName', val)
      }
    },
    sidebarFold: {
      get() {return this.$store.state.common.sidebarFold;},
      set(val) {this.$store.commit("common/updateSidebarFold", val);}
    },
  },
}
</script>
<style lang="less" scoped>
.menu-wrap{
  width: 200px;
  min-height: 1020px;
  background: url('../../assets/img/sidebar_bg.png') no-repeat;
  background-size: 100% 100%;
}
 
/deep/ .el-menu{
  background-color: transparent !important;
  .iconfont {
    font-size: 18px;
    vertical-align: sub;
    margin-right: 5px;
    display: inline-block;
    width: 20px;
    text-align: center;
  }
}
 
/deep/ .el-menu-item,
/deep/ .el-submenu__title{
  color: #fff;
 
  .iconfont{
    color: #fff;
  }
}
 
/deep/ .el-menu-item span,
/deep/ .el-submenu__title span{
  padding-left: 10px;
}
 
/deep/ .el-menu-item.is-active {
  -webkit-box-shadow: inset 5px 100px 0px -2px #0064B6;
  box-shadow: inset 5px 100px 0px -2px #0064B6;
}
 
/deep/ .el-submenu__title:hover,
/deep/ .el-menu-item:hover{
  background: #0064B6;
}
 
</style>

子組件SideBarItem

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<template>
    <!--    該菜單下還有子菜單-->
    <el-submenu v-if="menu.children.length" :index="menu.code" :popper-append-to-body=false>
        <template slot="title">
            <i class="iconfont icon-danganjianying"></i>
            <span>{{ menu.name }}</span>
        </template>
        <side-bar-item v-for="item in menu.children" :key="item.id" :menu="item"></side-bar-item>
    </el-submenu>
    <!--    該菜單下無子菜單-->
    <el-menu-item v-else :index="menu.code" @click="selectItem(menu.code, menu.path)">
        <i class="iconfont icon-danganjianying"></i>
        <span>{{ menu.name }}</span>
    </el-menu-item>
</template>
<script>
 
export default {
  name: 'SideBarItem',
  // props: ['menu'],
  props: {
      menu: {
      type: Object || {}
    }
  },
  data () {
    return {
 
    }
  },
  mounted () {
  },
  methods: {
    selectItem(code, path){
      // alert(name)
      console.log(code, path)
      this.$router.push(path)
      this.$store.commit('common/updateMenuActiveName', code)
    }
  },
}
</script>
<style lang="less" scoped>
.menu{
  width: 100%;
 
  .menu-item{
    height: 60px;
    line-height: 60px;
    text-align: left;
    color: #fff;
  }
 
  .sub-menu-item .el-menu-item{
    padding-right: 0;
  }
 
 /deep/ .el-menu-item .is-active{
    background-color: #0087df;
  }
 
  .menu-item:hover{
    background-color: #0087df;
  }
 
  .menu-item span{
    font-weight: 700;
  }
 
}
 
</style>

功能基本實現,但是出現一個bug,當鼠標點折疊時,會出現循環調用某個事件,導致棧溢出報錯,查看文章只需對子菜單設置屬性 :popper-append-to-body=“false” 即可
參考文章:Element-ui NavMenu子菜單使用遞歸生成時使用報錯

最后附上簡單的測試數據:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
testData: [
            {"id":"34161C2E8-7348-4439-8899-9A8039AE6AE4","pid":"0","code":"HOME","name":"首頁","path":"/home","type":null,"icon":null,"sysId":"2761C2E8-7348-4439-8899-9A8039AE6AE3","orderNo":0,"isCheck":null,"children":[]},
            {"id":"703DBEBD-F92C-4347-9203-F60A73153C3F","pid":"0","code":"WD","name":"溫度","path":"/temperature","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,"children":[]},
            {"id":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","pid":"0","code":"BJ","name":"報警","path":"/alarm","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,
              "children":[
                {"id":"1C99333D-886F-4AD6-93C4-7C5244E48247","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"FD","name":"防盜","path":"/burg","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},
                {"id":"1DBDF678-F51F-444A-B995-61E5D9CCA5AF","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"JL","name":"警鈴","path":"/bell","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},
                {"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF481","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"JS","name":"浸水","path":"/immersion","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},
                {"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF482","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"MJ","name":"門禁","path":"/punch","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},
                {"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF483","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"ZT","name":"狀態","path":"/state","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]}
              ]
            },
            {"id":"34161C2E8-7348-4439-8899-9A8039AE6AE5","pid":"0","code":"GZ","name":"工作","path":"/work","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,
              "children":[]
            },
            {"id":"0CD6B09A-AA43-4AE9-9AC7-29BC5AC83495","pid":"0","code":"SJ","name":"數據","path":"/data","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,
              "children":[]
            },
            {"id":"049C670D-A33E-4188-9206-B3F3B5DDE77B","pid":"0","code":"SP","name":"視頻","path":"/video","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},
            {"id":"0A15DBB6-3241-4C7F-AAD4-5417E7BBECAA","pid":"0","code":"RZ","name":"日志","path":"/log","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,
              "children":[]
            }
          ]

效果如圖:

vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

折疊后如圖:

vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航

到此這篇關于vue+elementUI組件遞歸實現可折疊動態渲染多級側邊欄導航的文章就介紹到這了,更多相關elementUI可折疊動態側邊欄導航內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/focusmickey/article/details/115801169

延伸 · 閱讀

精彩推薦
  • vue.jsVue多選列表組件深入詳解

    Vue多選列表組件深入詳解

    這篇文章主要介紹了Vue多選列表組件深入詳解,這個是vue的基本組件,有需要的同學可以研究下...

    yukiwu6752022-01-25
  • vue.js用vite搭建vue3應用的實現方法

    用vite搭建vue3應用的實現方法

    這篇文章主要介紹了用vite搭建vue3應用的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下...

    Asiter7912022-01-22
  • vue.jsVue2.x 項目性能優化之代碼優化的實現

    Vue2.x 項目性能優化之代碼優化的實現

    這篇文章主要介紹了Vue2.x 項目性能優化之代碼優化的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋...

    優小U9632022-02-21
  • vue.js詳解vue 表單綁定與組件

    詳解vue 表單綁定與組件

    這篇文章主要介紹了vue 表單綁定與組件的相關資料,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下...

    Latteitcjz6432022-02-12
  • vue.jsVue2.x-使用防抖以及節流的示例

    Vue2.x-使用防抖以及節流的示例

    這篇文章主要介紹了Vue2.x-使用防抖以及節流的示例,幫助大家更好的理解和學習使用vue框架,感興趣的朋友可以了解下...

    Kyara6372022-01-25
  • vue.js梳理一下vue中的生命周期

    梳理一下vue中的生命周期

    看過很多人講vue的生命周期,但總是被繞的云里霧里,尤其是自學的同學,可能js的基礎也不是太牢固,聽起來更是吃力,那我就已個人之淺見,以大白話...

    CRMEB技術團隊7992021-12-22
  • vue.jsVue項目中實現帶參跳轉功能

    Vue項目中實現帶參跳轉功能

    最近做了一個手機端系統,其中遇到了父頁面需要攜帶參數跳轉至子頁面的問題,現已解決,下面分享一下實現過程,感興趣的朋友一起看看吧...

    YiluRen丶4302022-03-03
  • vue.jsVue中引入svg圖標的兩種方式

    Vue中引入svg圖標的兩種方式

    這篇文章主要給大家介紹了關于Vue中引入svg圖標的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的...

    十里不故夢10222021-12-31
主站蜘蛛池模板: 九九九精品视频 | 猫咪社区免费资源在线观看 | 香蕉精品国产高清自在自线 | 久久精品熟女亚洲AV国产 | 香蕉久久久| 免费看男人使劲躁女人小说 | 国产一区日韩二区欧美三 | 人人最怕九月羊 | 国产精彩对白综合视频 | 爱情岛论坛亚洲品质自拍视频 | 18性夜影院午夜寂寞影院免费 | 男gaygays免费网站多人 | 成人免费淫片95视频观看网站 | 毛片在线播放a | 日韩欧美一区二区三区免费观看 | 青青草在观免费 | 免费看男人狂躁女人 | 扒开斗罗美女了的胸罩和内裤漫画 | 网站在线播放 | 亚洲七七久久综合桃花 | 日本老妇和子乱视频 | 2021麻豆剧果冻传媒入口永久 | 高h视频免费观看 | 特级夫妻大片免费在线播放 | 国产精彩视频 | 亚洲国产成人精品无码区5566 | 欧美精品成人a多人在线观看 | 涩情主播在线翻车 | 日本高清视频网址 | 亚洲欧美成人综合 | 国产成人啪精品视频站午夜 | 国产在线看片护士免费视频 | 亚洲妇熟xxxxx妇色黄 | 免费看a视频 | 国产成人精品曰本亚洲77美色 | 99午夜高清在线视频在观看 | 175m美女被网友灌醉啪啪玩脚 | 美女被绑着吸下部的故事 | 99精品国产美女福到在线不卡 | 日本激情网站 | 91tv在线观看|