基于 ElementUI 手撸穿梭树(一)

栏目: Node.js · 发布时间: 4年前

内容简介:现在,一直在忙着写一个自己独立承担前端部分的项目。公司刚完成的上百个开发工程师开发了一年的大项目,用的技术栈是React。 由于,自己主导的这个项目比较小,项目复杂度比之前的项目差远了。所以,就选了,开发灵活性没 React 高,但开发速度较快的 Vue,同时UI框架用的是 ElementUI。我们之前用 React 的大项目中,就有很多的地方用到了,穿梭书组件(两个ElementUI Tree 左树的数据可以穿梭到右面,右树的数据可以穿梭到左面)。好多节点的穿梭书是我们自己封装的。但这个小项目我们又用到了

现在,一直在忙着写一个自己独立承担前端部分的项目。公司刚完成的上百个开发工程师开发了一年的大项目,用的技术栈是React。 由于,自己主导的这个项目比较小,项目复杂度比之前的项目差远了。所以,就选了,开发灵活性没 React 高,但开发速度较快的 Vue,同时UI框架用的是 ElementUI。我们之前用 React 的大项目中,就有很多的地方用到了,穿梭书组件(两个ElementUI Tree 左树的数据可以穿梭到右面,右树的数据可以穿梭到左面)。好多节点的穿梭书是我们自己封装的。但这个小项目我们又用到了穿梭书,然而比较尴尬是,这次用的是 Vue,所以之前用 React 写的组件就只具备程序设计上的参考意义了。同时,我参考了,Element的树的写法的基础上,去是实现了基于Vue的穿梭树。由于,业务比较复杂,这篇文章就先之写 Tree 实现的核心思想吧!

Tree 程序结构

当然这个项目中记得引入 ElementUI。 树的每个节点都要记住自己的当前状态,树闭合展开选中的操作,也通过改变当前节点状态来改变。所以我们就需要,去把数据进行遍历,生成一个有状态,同时每个节点有改变的状态的构造树。

对数据进行遍历

树的 Data

const treeData = [
    {
      label: "一级 1",
      children: [
        {
          label: "二级 1-1",
        }
      ]
    },
    {
      label: "一级 2",
      children: [
        {
          label: "二级 2-1",
          children: [
            {
              label: "三级 2-1-1"
            }
          ]
        }
      ]
    }
]
复制代码

在 Tree.vue 中传入,将 treeData 传入构造函数中TreeStore。 new TreeStore({data: treeData}) 生成了我们想要的有状态,还可以通过调用内部函数改变自身节点状态的树形数据。

tree-store.js 代码

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
    })
  }
}
复制代码

node.js 代码

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; //展开关闭状态
        for (let option in options) {
            if (options.hasOwnProperty(option)) {
                this[option] = options[option]
            }
        }
        this.setData(this.data)
    }
    get isLeaf() {
        return !!this.childNodes.length
    }
    get label() {
        return getPropertyFromData(this, 'label');
    }
    setExpanded() { // 控制 expanded 来控制页面中树的闭合展开
        this.expanded = !this.expanded;
    }
    setData(data) {
        this.data = data;
        this.childNodes = []; // 子节点数组
        let 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);
    }
}
复制代码

将新的数据进行遍历

生成新的数据后,我们就可以在 Tree.vue 中对新数据进行遍历。将构造的数据中的文本渲染到页面中。

Tree.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>
复制代码

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> <!-- 使用了 elementUI 中的动画组件 -->
      <div
        v-show="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>
复制代码

好了,这个树是我用 Vue 实现的最最基本的树。抛去了一切业务逻辑,一切只剩最根本,很好理解很简单。当然写成这么简单,有很大一部分原因也希望我女朋友能够看懂。 后面的我会把有业务复杂逻辑的加进来。


以上所述就是小编给大家介绍的《基于 ElementUI 手撸穿梭树(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Web Designer's Idea Book

The Web Designer's Idea Book

Patrick Mcneil / How / 2008-10-6 / USD 25.00

The Web Designer's Idea Book includes more than 700 websites arranged thematically, so you can find inspiration for layout, color, style and more. Author Patrick McNeil has cataloged more than 5,000 s......一起来看看 《The Web Designer's Idea Book》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具