Vue 中递归调用节点组件自身实现无限节点的树

前言

在之前一篇《Vue 中使用渲染函数 render 实现无限节点的树》中我们介绍了如何使用 render 函数中的 h 函数来实现无限节点树的渲染,但这种方式有很多小伙伴们可能使用起来不是很习惯。有没有一种更加直观的方式来实现呢?其实是有的,就是我们可以递归调用树节点组件自身实现无限节点的树。

这种方式跟使用 jsx 可以轻松使用递归实现有点类似。废话不多数,先上在线 DemoGithub 上源码地址

代码分析

树节点组件 TreeNode.vue 代码如下:

<template>
  <li>
    <a
      :class="{'open': isOpen && data.children.length > 0, 'close': !isOpen && data.children.length > 0}"
      href="javascript:void(0);"
      class="name"
      @click="isOpen = !isOpen"
    >{{ data.name }}</a>
    <ul :class="{'hide': !isOpen}">
      <tree-node
        v-for="item in data.children"
        :key="item.id"
        :data="item"
      />
    </ul>
  </li>
</template>

<script>
export default {
  name: 'TreeNode',
  props: {
    data: {
      type: Object,
      default: () => {
        return {
          id: String(new Date().getTime() + Math.floor(9999 * Math.random())),
          name: '',
          children: []
        }
      }
    }
  },
  data () {
    return {
      isOpen: false
    }
  }
}
</script>

生成树页面 TreeDemoII.vue 代码如下:

<template>
  <article class="pageview">
    <header class="header fixed">
      <div class="container">
        <a
          class="back back_ico"
          href="javascript:void(0);"
          @click="goBack"
        ></a><span class="title">{{ msg }}</span>
      </div>
    </header>
    <section class="main">
      <div
        id="menu"
        class="clearfix menu"
      >
        <ul>
          <tree-node
            v-for="item in data"
            :key="item.id"
            :data="item"
          />
        </ul>
      </div>
    </section>
  </article>
</template>

<script>
import TreeNode from '../components/TreeNode'
import { goBack } from '../util/tools'

export default {
  name: 'TreeDemoII',
  components: {
    TreeNode
  },
  data () {
    return {
      msg: 'Tree Demo II',
      data: [
        {
          id: 0,
          name: '节点1',
          children: [
            {
              id: 1,
              name: '节点1-1',
              children: []
            },
            {
              id: 2,
              name: '节点1-2',
              children: [
                {
                  id: 7,
                  name: '节点1-2-1',
                  children: [
                    {
                      id: 10,
                      name: '节点1-2-1-1',
                      children: []
                    },
                    {
                      id: 11,
                      name: '节点1-2-1-2',
                      children: []
                    }
                  ]
                },
                {
                  id: 8,
                  name: '节点1-2-2',
                  children: []
                }
              ]
            }
          ]
        },
        {
          id: 3,
          name: '节点2',
          children: [
            {
              id: 4,
              name: '节点2-1',
              children: []
            },
            {
              id: 5,
              name: '节点2-2',
              children: []
            }
          ]
        },
        {
          id: 6,
          name: '节点3',
          children: []
        }
      ]
    }
  },
  methods: {
    goBack: goBack
  },
}
</script>

<style lang="scss" scoped>
.menu {
  /deep/ {
    .hide {
      display: none !important;
    }
    a {
      color: #000;
      padding: 10px 0;
      display: block;
    }
    ul {
      padding-left: 0px;
    }
    li {
      list-style: none;
      margin-left: 30px;
      border-left: 1px dashed #000;
      .name:before {
        content: "--";
      }
      .close:after {
        content: "[+]";
        margin-left: 10px;
      }
      .open:after {
        content: "[-]";
        margin-left: 10px;
      }
    }
  }
}
</style>

总结

这里主要是使用递归调用的思想来实现树节点,Vue 组件是支持在本组件中调用本组件的,这非常有趣,让我们可以更加灵活的实现一些特定场景的功能,比如树、无限菜单等。

作者: 博主

Talk is cheap, show me the code!

发表评论

邮箱地址不会被公开。

Captcha Code