Vue遞歸組件實現樹形結構菜單

    Tree 組件是遞歸類組件的典型表明,它經常使用於文件夾、組織架構、生物分類、國家地區等等,世間萬物的大多數結構都是樹形結構。使用樹控件能夠完整展示其中的層級關係,並具備展開收起選擇等交互功能。
    如圖所示,咱們要實現的就是這樣一個效果。以前咱們寫樹狀結構都是用jQuery來實現的,用Vue怎麼實現呢?vue

1、數據部分模擬

menuList:[
            {
                title:'菜單1',
                children:[
                    {
                        title:'菜單1-1',
                        children:[
                                {title:'菜單1-1-1'},
                                {title:'菜單1-1-2'},
                                {title:'菜單1-1-3'}
                            ]
                        },
                    {title:'菜單1-2'},
                    {title:'菜單1-3'}
                ]
            },
            {title:'菜單2'},
            {title:'菜單3'}
    ]
  
複製代碼

2、組件各部分實現

Menu.vuebash

首先咱們來寫個menu組件,這裏放個ul列表,裏面的內容,用插槽來表示。
<template>
    <ul>
       <slot></slot>
    </ul>
</template>

<script>
    export default {
        name: "Menu"
    }
</script>
複製代碼

MenuItem.vue架構

若是沒有子節點,所要展現的標題
<template>
    <li><slot></slot></li>
</template>

<script>
    export default {
        name: "MenuItem"
    }
</script>
複製代碼

SubMenu.vueapp

<template>
      <div>
          <div class="title" @click="change">
              <slot name="title"></slot>
              <!--name='title'區分插槽 -->
          </div>
          <div class="sub" v-show="flag">
              <slot></slot>
          </div>
      </div>
</template>

<script>
    export default {
        name: "SubMenu",
        data(){
            return {flag:false}
        },
        methods:{
            change(){
                this.flag=!this.flag
            }
        }
    }
</script>

<style>
.sub{
    padding-left:20px;
}
</style>
複製代碼

3、遞歸組件ReSubMenu.vue

這裏到了咱們實現樹形結構思想的重點,即遞歸組件。當咱們重複判斷有沒有子節點,並作出相應的展現的時候,這裏就可使用遞歸組件了。方便快捷,你值得擁有。ui

因爲有子節點會循環SubMenu這部分操做,因此單獨提出來放到ReSubMenu組件中
<template>
    <SubMenu>
        <template #title><!--#title爲了標識區分插槽-->
            {{data.title}}
        </template>
        <template v-for="child in data.children">
            <MenuItem :key="child.title" v-if="!child.children">{{child.title}}</MenuItem>
            <!--ReSubMenu跟name的名字保持一致,至關於循環使用該組件-->
            <ReSubMenu v-else :key="child.title" :data="child"></ReSubMenu>
        </template>
    </SubMenu>
</template>

<script>
    import SubMenu from './SubMenu'
    import MenuItem from './MenuItem'
    export default {
        name: "ReSubMenu",//可使用遞歸組件
        props:{
            data:{
                type:Object,//屬性校驗,爲對象數據類型,而且若是沒有賦值,默認給一個空對象
                default:()=>({})
            }
        },
        components:{
            SubMenu,
            MenuItem
        }
    }
</script>
複製代碼

4、整合實現

<div id="app">
   <Menu>
        <template v-for="menu in menuList">
                <MenuItem :key="menu.title" v-if="!menu.children">{{menu.title}}</MenuItem>
                <!--這部分是若是有孩子節點則會循環這部分操做,因此要單獨提取出來-->
               <!-- <SubMenu v-else>
                    <template #title>{{menu.title}}</template>
                    <template v-for="child in menu.children">
                        <MenuItem>{{child.title}}</MenuItem>
                    </template>
                </SubMenu>-->
                <ReSubMenu :key="menu.title" v-else :data="menu"></ReSubMenu>
        </template>
   </Menu>
<div>
<script>
    import Menu from './Menu'
    import MenuItem from './MenuItem'
   // import SubMenu from './SubMenu'
    import ReSubMenu from './ReSubMenu'
    export default {
        data(){
            return{
            //這裏的數據我就模擬一個了
                menuList:[
                    {
                        title:'菜單1',
                        children:[
                            {
                                title:'菜單1-1',
                                children:[
                                    {title:'菜單1-1-1'},
                                    {title:'菜單1-1-2'},
                                    {title:'菜單1-1-3'}
                                ]
                            },
                            {title:'菜單1-2'},
                            {title:'菜單1-3'}
                        ]
                    },
                    {title:'菜單2'},
                    {title:'菜單3'}
                ]
            }
        },
        components:{
            Menu,MenuItem,ReSubMenu
        }
    }
</script>
複製代碼

注:本節部分語句參考 https://juejin.im/book/5bc844166fb9a05cd676ebca/section/5bfcecc7f265da61682b102athis

相關文章
相關標籤/搜索