vue开发树形结构组件(组件递归)

本文实例为大家分享了vue开发树形结构组件的具体代码,供大家参考,具体内容如下

需求

一个页面,要显示商品分类,同时每个分类下面还拥有若干子类,子类也可以有子类。

要实现全选单选,子类被逐个全选父类也要标记选中。

第一反应就是树形结构,和递归调用。曾经在做WPF时记得有现成的组件,也学着写过对应的后台。这次我要自己写一个前端的组件了。

这只是我自己花了点时间写的一个vue组件,尚可优化及拓展。仅此与大家分享一下。

效果

实现

<template>
  <div id="TreeMenu">
    <div v-for="(node, index) in nodes" :class="{'TreeMenu-row-border-bottom': !depth}">
      <div class="TreeMenu-row">
        <img class="TreeMenu-row-selectimg" src="../assets/img/MembersPriceActivity/selected.png" @click="selectNode(0,node)" v-show="node.IsSelected"/>
        <img class="TreeMenu-row-selectimg" src="../assets/img/MembersPriceActivity/select.png" @click="selectNode(1,node)" v-show="!node.IsSelected"/>
        <div class="TreeMenu-row-firstdiv" :class="{'TreeMenu-row-border-bottom': node.ChildTypeList&&node.IsExpanded }"  @click="expandNode(!node.IsExpanded,node)">
          <label v-text="node.Name"></label>
          <img class="TreeMenu-row-arrowimg" src="../assets/img/MembersPriceActivity/top.png" v-if="node.ChildTypeList" v-show="!node.IsExpanded">
          <img class="TreeMenu-row-arrowimg" src="../assets/img/MembersPriceActivity/down.png" v-if="node.ChildTypeList" v-show="node.IsExpanded">
        </div>
        <TreeMenu :nodes="node.ChildTypeList" :fatherIndex="index" :depth="depth+1" v-on:selectFatherNode="selectFatherNode" v-if="node.ChildTypeList" v-show="!node.IsExpanded"></TreeMenu>
      </div>
    </div>
  </div>
</template>

js:

<script>
  export default{
    name: 'TreeMenu',
    data () {
      return {
        goodstype: {
          ID: '',
          ParentID: '',
          Name: '',
          Code: '',
          Level: 0,
          ImgUrl: null,
          ChildTypeList: []
        }
      }
    },
    props: {
      nodes: {
        type: Array,
        default: () => {
          return []
        }
      },
      fatherIndex: {
        type: Number,
        default: 0
      },
      depth: {
        type: Number,
        default: 0
      }
    },
    watch: {},
    created () {},
    mounted () {},
    destroyed () {},
    methods: {
      // 选中/取消 当前节点
      selectNode (choice, node) {
        node.IsSelected = choice
        this.selectChildrenNode(choice, node.ChildTypeList || [])
        this.$emit('selectFatherNode', choice, this.fatherIndex, this.nodes.every((node) => { return node.IsSelected === choice }))
      },
      // 子节点修改选中状态
      selectChildrenNode (choice, nodes, self) {
        let _self = self || this
        nodes.forEach((node) => { node.IsSelected = choice; _self.selectChildrenNode(choice, node.ChildTypeList || [], _self) })
      },
      // 作为父级节点检查是否需要修改选中状态(仅用于子节点调用)
      selectFatherNode (choice, index, childrenState) {
        if (choice) {
          // 若其[Index]节点下子节点均为被选中状态,该[Index]节点就应该被选中
          if (childrenState) {
            this.nodes[index].IsSelected = choice
            this.$emit('selectFatherNode', choice, this.fatherIndex, this.nodes.every((node) => { return node.IsSelected === choice }))
          }
        } else {
          // 若其[Index]节点下子节点有未被选中状态的,该[Index]节点就应该未选中
          this.nodes[index].IsSelected = choice
          this.$emit('selectFatherNode', choice, this.fatherIndex, false)
        }
      },
      // 展开/收起 当前节点
      expandNode (choice, node) {
        node.IsExpanded = choice
        if (!choice) {
          this.expandChildrenNode(choice, node.ChildTypeList)
        }
      },
      // 子节点收起
      expandChildrenNode (choice, nodes, self) {
        let _self = self || this
        nodes.forEach((node) => { node.IsExpanded = choice; _self.expandChildrenNode(choice, node.ChildTypeList || [], _self) })
      }
    }
  }
</script>

CSS:

<style lang="scss" scoped>
  #TreeMenu {
    .TreeMenu-row{
      margin-left: 30px;
      font-size: 15px;
      padding: 12px 0 0 0;
    }
    .TreeMenu-row-firstdiv{
      height: 32px;
      margin-left: 30px;
    }
    .TreeMenu-row-arrowimg{
      float: right;
      margin-right: 15px;
      width: 13px;
    }
    .TreeMenu-row-selectimg{
      float: left;
      width: 18px;
      vertical-align: text-bottom;
    }
    .TreeMenu-row-border-bottom{
      border-bottom: solid 1px #e6e6e6;
    }
    .TreeMenu-row-border-top{
      border-top: solid 1px #e6e6e6;
    }
  }
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue组件tree实现树形菜单

    vue 编写的树形菜单,小巧实用,支持vue1.0,vue2.0 v1.0 功能: 1.支持多级树目录 2.支持高亮点击的节点 3.支持展开点击节点 4.支持点击收缩节点时收缩所有子目录 5.支持自定义回调函数,点击节点时回调,参数为节点信息 用法:<launch-tree :list='list' :options='options'></launch-tree> list = [ { name: '一级目录', // 目录名字 isOpen: true, // 是否初始展开目录

  • Vue2组件tree实现无限级树形菜单

    一直打算偷懒使用个现成的树组件,但是在github上找了一大圈没有找到真正满足应用开发的树组件,所以没办法只能自己写了一个,开源出来希望可以帮助到需要的人,同时如果大家觉得好用,我可以顺带骗骗★(希望喜欢的朋友对我体力的肯定可以点下★ ),由于我也算刚接触vue,所以难免有所考虑不周的地方,希望大家在issue里面指正.组件重点是父子组件数据的共享和状态保持,我是利用了下vuex的思路,采用一个控制仓库完成. github 地址 vue-tree How to run demo npm inst

  • Vue.js组件tree实现无限级树形菜单

    分享一段用 <ul>和<li>标签实现tree的代码,可能写的不是很好,如果大家有更好的希望分享下. 代码看这里喽: html代码: <div class="tree"> <nav class='navbar'> <ul class='nav nav-stacked'> <template v-for='item in menus'> <li role='presentation' v-if='!item.c

  • Vue2递归组件实现树形菜单

    今天看了老长时间递归组件,官方给的教程太简便了,根本看不出到底怎么用.于是自己查网摸索了一下,这儿只把核心思想写出来. 效果如下图,点击后打开二级菜单,再点击后打开三级. //js //引子 //思想:当v-if='false'时,循环时进行的.所以一开始就设置为false. ggg:{ name:'gs', template:` <div> <p @click.stop='show=!show'>我是p标签</p> //这儿show必须要初始值为false,不然就是堆

  • Vue.js 递归组件实现树形菜单(实例分享)

    最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: import Vue from 'vue' Vue.config.debug = true import main from './components/main.vue' new Vue({ el: '#app', render: h => h(main) }) 它引入了一个组件 main.vue: <template> <div class="tree-m

  • vuejs使用递归组件实现树形目录的方法

    上篇文章我提到了通讯录的开发,里面的目录使用了vue的递归组件实现的树形目录,这篇文章就来讲讲如何实现树形目录吧! 首先实现效果如下,觉得菜单还是比较nice的是吧: 这边数据调用的是数据库的数据的,需要数据库进行数据的构造,这里涉及到java的构造多叉树的知识,后续我会另外写一篇文章详细讲解,这里讲下前端. 数据可以先构造json使用,这里用到的格式大概如下,以childList来嵌套子菜单: { id:YH, name:银行, pid:0, childList:[{ id:YH******,

  • 用 Vue.js 递归组件实现可折叠的树形菜单(demo)

    在Vue.js中一个递归组件调用的是其本身,如: Vue.component('recursive-component', { template: `<!--Invoking myself!--> <recursive-component></recursive-component>` }); 递归组件常用于在blog上显示注释.嵌套的菜单,或者基本上是父和子相同的类型,尽管具体内容不同.例如: 现在给您演示一下如何有效地使用递归组件,我将通过建立一个可扩展/收缩的树形

  • 基于 Vue 的树形选择组件的示例代码

    本文介绍了基于 Vue 的树形选择组件.分享给大家,具体如下: 系统要求:Vue 2 基本特性 完美的多级联动效果 支持无限多的分级 有 全选.半选.不选 三种状态  截图展示 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="icon" href="https://v1-c

  • Vue组件模板形式实现对象数组数据循环为树形结构(实例代码)

    数据结构为数组中包含对象--树形结构,用Vue组件的写法实现以下的效果: 树形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据.本文为用Vue实现方式,另有一篇为用knockout.js的实现方法. html代码 <div id="table-component-div"> <table-component v-for="item in data1" v-bind:list="item"></ta

  • Vue.js递归组件构建树形菜单

    在Vue.js中一个递归组件调用的是其本身,如: Vue.component('recursive-component', { template: `<!--Invoking myself!--> <recursive-component></recursive-component> }); 递归组件常用于在blog上显示注释.嵌套的菜单,或者基本上是父和子相同的类型,尽管具体内容不同.例如: 现在给您演示一下如何有效地使用递归组件,我将通过建立一个可扩展/收缩的树形菜

随机推荐