美文网首页Vue 组件库
Vue menu 递归组件

Vue menu 递归组件

作者: 阿畅_ | 来源:发表于2019-06-18 18:38 被阅读0次

分享一个用递归的方式写 menu 组件

vue 利用递归组件写导航

  • 为什么要用递归的方式写 ?

原因可以有几点: 大大简化了代码量,根据 JOSN 数据快速的渲染出 DOM 结构。不需要配置太多的参数。
缺点:因为使用 JSON 的方式传递了一整个数据,所有可扩展性不是很强。

<template>
  <div class="ac-menu-container">
    <template v-for="(data, index) in menuData">
      <div class="menu-childrens" :key="index">
        <div
          class="menu-item"
          @click.stop="selectClick(data, index)"
          :class="{
            active: selectItem == data.id,
          }"
          :style="{ paddingLeft: `${10*level}px` }">
            <span>{{ data.name }}</span>
            <div class="right-icon">
              <i
                class="icon el-icon-arrow-down"
                :class="{ expanded: data.expand }"
                v-show="hasChildren(data.children)"></i>
            </div>
            // toolbar 部分
            <div class="operation isHover" v-show="isHover">
              <button
                icon="el-icon-edit"
                @click.stop="handleEdit(data, index, true)">编辑</button>
    
                <el-button
                  class="icon-plus"
                  @click.stop="handleCreate(data, index, true)">新建子分类</el-button>
            </div>
          </div>
        // 递归组件
        <template v-if="data.expand && level < 3">
          <ac-munu
            :menuData="data.children"
            :level="setLeval"
            v-model="selectItem"
            @on-change="handleChange"
            @on-edit="childrenEdit"
            @on-delete="childrenDelete"
            @on-create="childrenCreate"
            :isHover="isHover"></ac-munu>
        </template>
      </div>
    </template>
  </div>
</template>
  • js 部分
<script>
  export default {
    name: 'ac-munu',
    props: {
      value: {
        type: [String, Number],
      },
      menuData: {
        type: [Array, Object],
        default: () => {}
      },
      level: {
        type: Number,
        default: 1
      },
      isHover: {
        type: Boolean,
        default: true
      }
    },

    computed: {
      setLeval() { // 当前的层级
        return this.level + 1
      },
      selectItem: { // 双向绑定 v-model
        get() {
          return this.value
        },
        set(value) {
          this.$emit('input', value)
        },
      }
    },

    methods: {
      selectClick(item, index) {
  
        if (item.expand) {
          if (this.hasChildren(item.children)) {
            item.expand = !item.expand
          }
          return
        }

        if (this.hasChildren(item.children)) {
          item.expand = !item.expand
          return
        }

        if(this.selectItem === item.id) return
        this.selectItem = item.id

        this.$emit('on-change', item, this.level, index)
      },

      hasChildren(option) {
        if(!Array.isArray(option)) return false
        return option.length > 0
      },

      handleChange(item, index) {
        this.$emit('on-change', item, this.level, index)
      },

      handleEdit(item, index, state) {
        this.$emit('on-edit', item, index, state)
      },

      handleDelete(item, index) {
        this.$emit('on-delete', item, index)
      },

      handleCreate(item, index, state) {
        this.$emit('on-create', item, index, state)
      },

      // 下面是除第一层以外的事件
      childrenEdit(item, index, state) {
        this.$emit('on-edit', item, index, state)
      },

      childrenDelete(item, index) {
        this.$emit('on-delete', item, index)
      },

      childrenCreate(item, index, state) {
        this.$emit('on-create', item, index, state)
      }
    }
  }
</script>
  • 调用 部分
 <sc-menu
    :menuData="menuData"
    v-model="current"
    @on-change="menuChange"
    @on-edit="menuEdit"
    @on-delete="menuDelete"
    @on-create="menuCrateChildren"></sc-menu>

  // JSON 数据  从后端取得数据
  munuData: [
    {
      id:1,
      name: '测试标题1',
      expand: false,
      children: [
        {
          id:2,
          name: '测试第一层子标题',
          expand: false,
          children: [
            {
              id: 3,
              name: '测试第二层子标题',
            }
          ]
        }
      ]
    },
    {
      id:4,
      name: '测试标题2',
      expand: false,
      children: [
        {
          id:5,
          name: '测试第一层子标题',
          expand: false,
          children: [
            {
              id: 6,
              name: '测试第二层子标题',
            }
          ]
        }
      ]
    }
  ]
  • 最后生成的效果
menu.png

如果你有更好的写法或有什么疑问欢迎留言,如果想要源码欢迎留言或私信。

相关文章

  • Vue menu 递归组件

    分享一个用递归的方式写 menu 组件 vue 利用递归组件写导航 为什么要用递归的方式写 ? 原因可以有几点: ...

  • 39.React动态菜单组件实现

    实现动态菜单主要是使用递归+Menu组件来实现的。递归用来二级以及多级菜单。判断menu是否有children,有...

  • 树形结构递归/原生js实现/vue递归组件

    原生js实现递归渲染 Vue2.0递归组件

  • Ant Design 动态菜单设计(随笔记录)

    建立文件目录side-menu,side-menu.vue未左侧菜单组件 新建router.js文件,定义路由 r...

  • vue 局部组件递归

    vue只有全局注册的组件才能递归调用吗? 最近在开发 npm 组件库,需要递归使用组件,组件间存在相互依赖关系。搜...

  • 【vue3】vue3+element-plus,menu默认激活

    vue3+vite+element-plus,el-menu组件中,刷新页面后,默认激活选中的菜单 el-menu...

  • 父子组件通信

    vue之父子组件间通信实例讲解(props、emit) Vue.js 递归组件实现树形菜单(实例分享)

  • vue递归组件

    今天在阅读vue文档的时候,发现还有一个递归组件,平时没有注意到。递归组件就是在自己组件的模板中调用自己,此时组件...

  • vue递归组件

    1.效果图 2.布局 模板: 实例以及函数方法:

  • vue 递归组件

    递归组件的定义 每个组件都有一个name属性。当你注册全局组件的时候这个全局的ID会设置成这个组件的name属性 ...

网友评论

    本文标题:Vue menu 递归组件

    本文链接:https://www.haomeiwen.com/subject/fmoxaqtx.html