vue之树状导航栏(TreeNav)

功能
  • 传入一个普通对象,生成菜单
  • 能够代开和关闭某个节点。
效果

实现后效果如下
在这里插入图片描述

原理

重点在于Vue组件可以嵌套使用。

思路

首先实现一个组件TreeNavItrem,它表示树中的其他子树或叶子结点。然后实现TreeNav组件,它表示树的根节点,根节点没有内容,只作为一个容器。

代码

注意,使用了阿里的图标iconfont。

TreeNavItem.vue

<template>
    <div class="nav-tree-item-group">
        <div class="nav-tree-item-name" @click="toggleTree">
            <i class="iconfont icon-arrow-right" :class="{ 'icon-arrow-right-open': isOpen }" v-if="isTree"></i>
            {{treeData.name}}
        </div>
        <ul class="nav-tree-item-subTree" v-show="isOpen" v-if="isTree">
            <li v-for="(item,index) in treeData.subTree" :key="index">
                <TreeNavItem :treeData="item"></TreeNavItem>
            </li>
        </ul>
    </div>
</template>
<script>
import "@/assets/icon/iconfont/iconfont.css"
/**
 * 树状导航栏中的一项
 * tree item结构:
 *  普通树:
    {
        name:"title"
    }
    子树:
    {
        name:"subtitle 1",
        subTree:[
            {name:"title 1.1"},
            {name:"title 1.2"}
        ]
    }
 */
export default {
    name:"TreeNavItem",
    data:function(){
        return {
            isOpen:false
        }
    },
    props:{
        /**
         * 树的数据
         */
        treeData:{
            type:Object,
            default:[{name:"title"}]
        }
    },
    computed:{
        /**
         * 是树?即非叶子节点
         */
        isTree(){
            return this.treeData.subTree && this.treeData.subTree.length>0;
        }
    },
    methods:{
        /**
         * 数打开与关闭状态的切换
         * 前提非叶子节点
         */
        toggleTree(){
            if(this.isTree){
                this.isOpen=!this.isOpen;
            }
        }
    }
}
</script>
<style>
.nav-tree-item-subTree{
    list-style-type: none;
    padding-left:0;
}
.nav-tree-item-subTree > li{
    margin-bottom:0.2rem;
    margin-left:1rem;
}
.nav-tree-item-name{
    margin-left: 1rem;
    position: relative;
}
.icon-arrow-right{
    display:inline-block;
    position: absolute;
    left: -1rem;
    font-size: 0.5rem;
    color: green;
    font-weight: bolder;
    top: 50%;
    transform: translateY(-50%);
    transition: transform 0.5s;
}
.icon-arrow-right-open{
    transform: translateY(-50%) rotate(90deg);
}
</style>

TreeNav.vue

<template>
    <div class="nav-tree-group">
        <ul class="nav-tree">
            <li class="nav-tree-item" v-for="(item,index) in treeData" :key="index">
                <TreeNavItem :treeData="item"></TreeNavItem>
            </li>
        </ul>
    </div>
</template>

<script>
import TreeNavItem from "./TreeNavItem"
/**
 * 树状导航栏
 * 数据格式如下所示:
let treeData=[
    {name:"title 1"},
    {name:"title 2"},
    {
        name:"title 3",
        subTree:[
            {name:"title 3.1"},
            {name:"tile 3.2"}
        ]
    },
    {
        name:"title 4",
        subTree:[
            {name:"title 4.1"},
            {name:"title 4.2"},
            {
                name:"title 4.3",
                subTree:[
                    {name:"title 4.3.1"},
                    {name:"title 4.3.2"},
                    {name:"title 4.3.3"}
                ]
            }
        ]
    }
]
*/
export default {
    name:"TreeNav",
    props:{
        /**
         * 树的数据
         */
        treeData:{
            type:Array,
            default:[{name:"title"}]
        }
    },
    components:{
        TreeNavItem
    }    
}
</script>
<style>
.nav-tree-group{
    background-color: white;
    padding:0.5rem;
}
.nav-tree{
    list-style-type: none;
    padding-left:0;
}
.nav-tree-item{
    margin-bottom:0.2rem;
}
</style>

用于展示效果的App.vue

<template>
  <div id="app">
    <TreeNav class="nav-sidebar" :treeData="titles"></TreeNav>
  </div>
</template>

<script>
import MarkdownEditor from "@/components/MarkdownEditor"
import TreeNav from "@/components/Tree/TreeNav"

export default {
  name: 'app',
  data:function(){
    return {
      titles:[
          {name:"用户管理"},
          {name:"订单管理"},
          {
              name:"商品管理",
              subTree:[
                  {name:"添加商品"},
                  {name:"查看商品"}
              ]
          },
          {
              name:"个人信息",
              subTree:[
                  {name:"修改信息"},
                  {name:"添加信息"},
                  {
                      name:"聊天记录",
                      subTree:[
                          {name:"聊天"},
                          {name:"删除好友"},
                          {name:"添加好友"}
                      ]
                  }
              ]
          }
      ]
    }
  },
  components:{
    MarkdownEditor,
    TreeNav
  }
}
</script>

<style>
#app{
  position: fixed;
  top:0;
  bottom:0;
  left:0;
  right:0;
  background-color: #eee;
}
.nav-sidebar{
  width:8rem;
}
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值