Now, I have been busy writing a project to undertake the front-end part on my own. The company just completed hundreds of development engineers to develop a big project for a year, using the technology stack is React. Since the project I led was relatively small, the complexity of the project was far worse than the previous one. So we chose Vue, which has less flexibility than React but is faster, and uses ElementUI for the UI framework. In our React project, there was a lot of use of the shuttle book component (data from the left ElementUI Tree can be moved to the right and data from the right ElementUI Tree can be moved to the left). Many of the nodes of the shuttle book is our own encapsulation. For this small project, we used the Shuttle book again, but awkwardly, we used Vue, so the React component was just a programming reference. At the same time, I refer to the writing method of Element tree, to realize the Vue based shuttle tree. Because, the business is more complex, this article first write Tree implementation of the core idea!

Tree program structure

Remember to include ElementUI in this project, of course. Each node in the tree remembers its current state, and the selected operation of tree closure expansion is also changed by changing the current node state. So what we need to do is, we need to iterate through the data, generate a construct tree that has a state, and each node has a state that changes.

Iterate over the data

The tree’s Data

const treeData = [
    {
      label: "Level 1",
      children: [
        {
          label: "The secondary 1-1",
        }
      ]
    },
    {
      label: "Level 2",
      children: [
        {
          label: "Secondary 2-1",
          children: [
            {
              label: "Triple the 2-1-1"}]}]Copy the code

Passed in tree. vue, pass treeData to TreeStore in the constructor. New TreeStore({data: treeData}) generates the desired treeData that is stateful and can change the state of its own nodes by calling internal functions.

The tree – store. Js code

import Node from './node.js'
export default class TreeStore {
  constructor(options) {
    for (let option in options) {
      if (options.hasOwnProperty(option)) {
        this[option] = options[option]
      }
    }
    this.root = new Node({
      data: this.data,
      store: this
    })
  }
}
Copy the code

Node. Js code

import objectAssign from 'element-ui/src/utils/merge';
const getPropertyFromData = function(node, prop) {
    const data = node.data || {};
    if (typeof prop === 'string') {
        return data[prop];
    } else {
        throw new Error('label data type is not string'); }};export default class Node {
    constructor(options) {
        this.level = 0;
        this.childNodes = [];
        this.expanded = true; // Expand the closed statefor (let option in options) {
            if (options.hasOwnProperty(option)) {
                this[option] = options[option]
            }
        }
        this.setData(this.data)
    }
    get isLeaf() {
        return!!!!! this.childNodes.length } getlabel() {
        return getPropertyFromData(this, 'label');
    }
    setExpanded() {// Control expanded to control the closed expansion of the tree in the page this.expanded =! this.expanded; }setData(data) { this.data = data; this.childNodes = []; // Array of child nodeslet children;
        if (this.level === 0 && this.data instanceof Array) {
            children = this.data;
        } else {
            children = getPropertyFromData(this, 'children') | | []; }for (let i = 0; i < children.length; i++) {
            this.insertChild({ data: children[i] });
        }
    }
    insertChild(child, index, batch) {
        if(! child) throw new Error('insertChild error: child is required.');
        if (!(child instanceof Node)) {
            objectAssign(child, {
                parent: this,
                store: this.store
            });
            child = new Node(child);
        }

        child.level = this.level + 1;
        this.childNodes.push(child);
    }
}
Copy the code

The new data is traversed

After the new data is generated, we can walk through the new data in tree.vue. Renders the text from the constructed data to the page.

The code in the Tree. The vue

<template>
  <div class="el-tree" role="tree">
    <tree-node
      v-for="(child, index) in root.childNodes"
      :key="index"
      :node="child"
     />
  </div>
</template>

<script>
import TreeStore from "./modal/tree-store.js";
import TreeNode from "./TreeNode.vue";

export default {
  name: "Tree".data() {
    return {
      store: null,
      root: null
    };
  },
  props: {
    data: {
      type: Array
    }
  },
  created() {
    this.store = new TreeStore({
      data: this.data
    })
    this.root = this.store.root;
  },
  components: {
    TreeNode
  }
};
</script>
Copy the code

The code in the TreeNode. Vue

<template>
  <div class="tree">
    <div class="el-tree-node__content">
      <span
        :class="[ {'expanded': node.expanded}, 'el-tree-node__expand-icon' ]"
        class="el-icon-caret-right"
        @click.stop="handleExpandIconClick"
      ></span>
      <span class="el-tree-node__label">{{node.label}}</span> </div> <el-collapse-transition> <! <div v-show= -- use animation components in elementUI"node.expanded"
        class="el-tree-node__children"
        style="padding-left: 18px;"
      >
        <tree-node
          v-for="(item, index) in node.childNodes"
          :key="index"
          :node="item"
        />
      </div>
    </el-collapse-transition>
  </div>
</template>

<script>
export default {
  name: "TreeNode",
  props: {
    node: Object
  },
  data() {
    return {
      data: Array,
      isExpande: true
    };
  },
  methods: {
    handleExpandIconClick() { this.node.setExpanded(); }}}; </script>Copy the code

Ok, this tree is the most basic tree I’ve implemented with Vue. Throw away all the business logic, everything left to the most fundamental, easy to understand very simple. Of course, there’s a big reason why it’s so easy to write, and I want my girlfriend to understand it. I’ll add in the ones that have complex business logic.