vue ztree 的使用

ztree 是一个很经典的基于jquey开发的树结构编辑展示UI组件库。

https://gitee.com/zTree/zTree_v3

 

gitee上有一个很适合vue使用的ztree封装库,

https://gitee.com/astinlee_admin/Vue-Giant-Tree/tree/master

 

但是这个库有个问题。

打包后的代码引入到项目中会报错。

怎么办呢?

此时,我们应该“格局打开”,打包不行,不打包,作为代码片段引入不就可以了?

其实这个项目里面关键的只有一个文件,ztree.vue。

<template>
  <div class="ztree" :id="ztreeId"></div>
</template>

<script>
import * as $ from "jquery";
if(!window.jQuery){
  window.jQuery = $;
}

require("@ztree/ztree_v3/js/jquery.ztree.all"); 

export default {
  props: {
    setting: {
      type: Object,
      require: false,
      default: function(){
        return {}
      }
    },
    nodes: {
      type: Array,
      require: true,
      default: function(){
        return []
      }
    }
  },
  data(){
    return {
      ztreeId: 'ztree_'+ parseInt(Math.random() * 1e10),
      ztreeObj: null,
      list: [],
      ztreeSetting: {
        view: {
          showIcon: false         // default to hide icon
        },
        callback: {
          onAsyncError: (...arg) => {
            this.$emit('onAsyncError', ...arg)
          },
          onAsyncSuccess: (...arg) => {
            this.$emit('onAsyncSuccess', ...arg)
          },
          onCheck: (...arg) => {
            this.$emit('onCheck', ...arg)
          },
          onClick: (...arg) => {
            this.$emit('onClick', ...arg)
          },
          onCollapse: (...arg) => {
            this.$emit('onCollapse', ...arg)
          },
          onDblClick: (...arg) => {
            this.$emit('onDblClick', ...arg)
          },
          onDrag: (...arg) => {
            this.$emit('onDrag', ...arg)
          },
          onDragMove: (...arg) => {
            this.$emit('onDragMove', ...arg)
          },
          onDrop: (...arg) => {
            this.$emit('onDrop', ...arg)
          },
          onExpand: (...arg) => {
            this.$emit('onExpand', ...arg)
          },
          onMouseDown: (...arg) => {
            this.$emit('onMouseDown', ...arg)
          },
          onMouseUp: (...arg) => {
            this.$emit('onMouseUp', ...arg)
          },
          onRemove: (...arg) => {
            this.$emit('onRemove', ...arg)
          },
          onRename: (...arg) => {
            this.$emit('onRename', ...arg)
          },
          onRightClick: (...arg) => {
            this.$emit('onRightClick', ...arg)
          }
        }
      }
    }
  },
  watch: {
    nodes: {
      handler: function(nodes){
        this.list = nodes;

        // update tree
        if(this.ztreeObj){
          this.ztreeObj.destroy();
        }
        this.$nextTick(() => {
          this.ztreeObj = $.fn.zTree.init($("#"+this.ztreeId), Object.assign({}, this.ztreeSetting, this.setting), this.list);
          this.$emit('onCreated', this.ztreeObj)
        })
      },
      deep: true,
      immediate: true
    }
  }
}
</script>

<style scoped>
/* beauty ztree! */
.ztree {
  text-align:left;
  font-size: 14px;
}
.ztree >>> li {
  list-style-type: none;
  white-space: nowrap;
  outline: none;
}
.ztree >>> li ul {
  position: relative;
  padding: 0 0 0 20px;
  margin: 0;
}
.ztree >>> .line:before {
  position: absolute;
  top: 0;
  left: 10px;
  height: 100%;
  content: '';
  border-right: 1px dotted #dbdbdb;
}
.ztree >>> .roots_docu:before,
.ztree >>> .roots_docu:after,
.ztree >>> .center_docu:before,
.ztree >>> .bottom_docu:before,
.ztree >>> .center_docu:after,
.ztree >>> .bottom_docu:after {
  position: absolute;
  content: '';
  border: 0 dotted #dbdbdb;
}
.ztree >>> .roots_docu:before {
  left: 10px;
  height: 50%;
  top:50%;
  border-left-width: 1px;
}
.ztree >>> .roots_docu:after {
  top: 50%;
  left: 11px;
  width: 50%;
  border-top-width: 1px;
}
.ztree >>> .center_docu:before {
  left: 10px;
  height: 100%;
  border-left-width: 1px;
}
.ztree >>> .center_docu:after {
  top: 50%;
  left: 11px;
  width: 50%;
  border-top-width: 1px;
}
.ztree >>> .bottom_docu:before {
  left: 10px;
  height: 50%;
  border-left-width: 1px;
}
.ztree >>> .bottom_docu:after {
  top: 50%;
  left: 11px;
  width: 50%;
  border-top-width: 1px;
}
.ztree >>> li a {
  display: inline-block;
  line-height: 22px;
  height: 22px;
  margin: 0;
  padding: 0 3px;
  cursor: pointer;
  transition: none;
  vertical-align: middle;
  color: #555555;
}
.ztree >>> .curSelectedNode {
  color: #000;
  border-radius: 4px;
  background-color: #c9e9f7;
}
.ztree >>> .curSelectedNode_Edit {
  height: 20px;
  opacity: 0.8;
  color: #000;
  border: 1px #6cc2e8 solid;
  background-color: #9dd6f0;
}
.ztree >>> .tmpTargetNode_inner {
  opacity: 0.8;
  color: #fff;
  background-color: #4fcbf0;
  filter: alpha(opacity=80);
}
.ztree >>> .rename {
  font-size: 12px;
  line-height: 22px;
  width: 80px;
  height: 22px;
  margin: 0;
  padding: 0;
  vertical-align: top;
  border: 0;
  background: none;
}
.ztree >>> .button {
  position: relative;
  display: inline-block;
  line-height: 22px;
  height: 22px;
  width: 22px;
  cursor: pointer;
  text-align: center;
  vertical-align: middle;
}

.ztree >>> .button.edit {
  color: #25ae88;
}
.ztree >>> .button.remove {
  color: #CB4042;
}
.ztree >>> .button.chk {
  position: relative;
  width: 14px;
  height: 14px;
  margin: 0 4px 0 0;
  border: 1px solid #d7dde4;
  border-radius: 2px;
  background: #fff;
}
.ztree >>> .chk.radio_true_full,
.ztree >>> .chk.radio_false_full,
.ztree >>> .chk.radio_true_full_focus,
.ztree >>> .chk.radio_false_full_focus,
.ztree >>> .chk.radio_false_disable,
.ztree >>> .chk.radio_true_disable,
.ztree >>> .chk.radio_true_part,
.ztree >>> .chk.radio_false_part,
.ztree >>> .chk.radio_true_part_focus,
.ztree >>> .chk.radio_false_part_focus {
  border-radius: 8px;
}
.ztree >>> .button.chk:after {
  position: absolute;
  top: 1px;
  left: 4px;
  width: 4px;
  height: 8px;
  content: '';
  transition: -webkit-transform 0.2s ease-in-out;
  transition: transform 0.2s ease-in-out;
  transition: transform 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out;
  -webkit-transform: rotate(0deg) scale(0);
          transform: rotate(0deg) scale(0);
  border-right: 2px solid #fff;
  border-bottom: 2px solid #fff;
}
.ztree >>> .button.checkbox_false_full_focus {
  border-color: #ccc;
}
.ztree >>> .button.checkbox_true_full,
.ztree >>> .button.checkbox_true_full_focus,
.ztree >>> .button.checkbox_true_part,
.ztree >>> .button.checkbox_true_part_focus,
.ztree >>> .button.checkbox_true_disable {
  border-color: #39f;
  background-color: #39f;
}
.ztree >>> .button.checkbox_true_full:after,
.ztree >>> .button.checkbox_true_full_focus:after,
.ztree >>> .button.checkbox_true_disable:after {
  -webkit-transform: rotate(45deg) scale(1);
          transform: rotate(45deg) scale(1);
}
.ztree >>> .button.checkbox_true_part:after,
.ztree >>> .button.checkbox_true_part_focus:after {
  top: 5px;
  left: 2px;
  width: 10px;
  height: 1px;
  -webkit-transform: rotate(0deg) scale(1);
          transform: rotate(0deg) scale(1);
  border-right: 0;
}
.ztree >>> .button.radio_true_full,
.ztree >>> .chk.radio_true_full_focus,
.ztree >>> .chk.radio_true_part,
.ztree >>> .chk.radio_true_part_focus {
  border-color: #39f;
}
.ztree >>> .button.radio_true_full:after,
.ztree >>> .chk.radio_true_full_focus:after,
.ztree >>> .chk.radio_true_part:after,
.ztree >>> .chk.radio_true_part_focus:after {
  top: 3px;
  left: 3px;
  width: 8px;
  -webkit-transform: rotate(0deg) scale(1);
          transform: rotate(0deg) scale(1);
  border: 0;
  border-radius: 4px;
  background: #39f;
}
.ztree >>> .button.checkbox_true_disable,
.ztree >>> .button.checkbox_false_disable,
.ztree >>> .chk.radio_false_disable,
.ztree >>> .chk.radio_true_disable {
  cursor: not-allowed;
}
.ztree >>> .button.checkbox_false_disable {
  background-color: #f3f3f3;
}
.ztree >>> .button.noline_close:before,
.ztree >>> .button.noline_open:before,
.ztree >>> .button.root_open:before,
.ztree >>> .button.root_close:before,
.ztree >>> .button.roots_open:before,
.ztree >>> .button.roots_close:before,
.ztree >>> .button.bottom_open:before,
.ztree >>> .button.bottom_close:before,
.ztree >>> .button.center_open:before,
.ztree >>> .button.center_close:before {
  position: absolute;
  top: 5px;
  left: 5px;
  content: '';
  transition: -webkit-transform ease 0.3s;
  transition: transform ease 0.3s;
  transition: transform ease 0.3s, -webkit-transform ease 0.3s;
  -webkit-transform: rotateZ(0deg);
          transform: rotateZ(0deg);
  -webkit-transform-origin: 25% 50%;
          transform-origin: 25% 50%;
  border: 6px solid;
  border-color: transparent transparent transparent #666;
}
.ztree >>> .button.noline_open:before,
.ztree >>> .button.root_open:before,
.ztree >>> .button.roots_open:before,
.ztree >>> .button.bottom_open:before,
.ztree >>> .button.center_open:before {
  -webkit-transform: rotateZ(90deg);
          transform: rotateZ(90deg);
}
.ztree >>> .button.ico_loading {
  margin-right: 2px;
  background: url('data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7') 0 center no-repeat;
}
.ztree >>> .tmpTargetzTree {
  opacity: 0.8;
  background-color: #2EA9DF;
  filter: alpha(opacity=80);
}
.ztree >>> .tmpzTreeMove_arrow {
  position: absolute;
  width: 18px;
  height: 18px;
  color: #4fcbf0;
}
.ztree >>> .ztree.zTreeDragUL {
  overflow: hidden;
  position: absolute;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  opacity: 0.8;
  border: 1px #176b53 dotted;
  background-color: #dbdbdb;
  filter: alpha(opacity=80);
}
.zTreeMask {
  position: absolute;
  z-index: 10000;
  opacity: 0.0;
  background-color: #cfcfcf;
  filter: alpha(opacity=0);
}
</style>
ztree.vue

 

这样我们的项目文件引入这个文件就可以了。

我们现在还有2个问题

1 确保测试json是个正常的json文件。

这里有个正常的json,可以拿去用。

{
  "code": 10000,
  "success": true,
  "data": [{
    "id": "779893942852403200-1",
    "taskId": "779893942852403200",
    "zxbNum": null,
    "struId": "",
    "name": "-",
    "orgCode": "",
    "isLeaf": false,
    "majCode": "1",
    "taskOrder": 0,
    "children": [{
      "id": "779893942852403200-1-13862",
      "taskId": "779893942852403200",
      "zxbNum": 1,
      "struId": "13862",
      "name": "-",
      "orgCode": "9767",
      "isLeaf": false,
      "majCode": "1",
      "taskOrder": 2,
      "children": [{
        "id": "779893942852403200-1-13823",
        "taskId": "779893942852403200",
        "zxbNum": 1,
        "struId": "13823",
        "name": "-",
        "orgCode": "9728",
        "isLeaf": false,
        "majCode": "1",
        "taskOrder": 3,
        "children": [{
          "id": "779893942852403200-1-14013",
          "taskId": "779893942852403200",
          "zxbNum": 1,
          "struId": "14013",
          "name": "-",
          "orgCode": "9918",
          "isLeaf": true,
          "majCode": "1",
          "taskOrder": 4,
          "children": [],
          "struType": "6"
        }],
        "struType": "5"
      }],
      "struType": "4"
    }],
    "struType": ""
  }, {
    "id": "779893942852403200-3",
    "taskId": "779893942852403200",
    "zxbNum": null,
    "struId": "",
    "name": "-",
    "orgCode": "",
    "isLeaf": false,
    "majCode": "3",
    "taskOrder": 0,
    "children": [{
      "id": "779893942852403200-3-13862",
      "taskId": "779893942852403200",
      "zxbNum": 1,
      "struId": "13862",
      "name": "-",
      "orgCode": "9767",
      "isLeaf": false,
      "majCode": "3",
      "taskOrder": 2,
      "children": [{
        "id": "779893942852403200-3-13823",
        "taskId": "779893942852403200",
        "zxbNum": 1,
        "struId": "13823",
        "name": "-",
        "orgCode": "9728",
        "isLeaf": true,
        "majCode": "3",
        "taskOrder": 3,
        "children": [],
        "struType": "5"
      }],
      "struType": "4"
    }],
    "struType": ""
  }, {
    "id": "779893942852403200-4",
    "taskId": "779893942852403200",
    "zxbNum": null,
    "struId": "",
    "name": "-",
    "orgCode": "",
    "isLeaf": false,
    "majCode": "4",
    "taskOrder": 0,
    "children": [{
      "id": "779893942852403200-4-13862",
      "taskId": "779893942852403200",
      "zxbNum": 1,
      "struId": "13862",
      "name": "-",
      "orgCode": "9767",
      "isLeaf": false,
      "majCode": "4",
      "taskOrder": 2,
      "children": [{
        "id": "779893942852403200-4-13823",
        "taskId": "779893942852403200",
        "zxbNum": 1,
        "struId": "13823",
        "name": "-",
        "orgCode": "9728",
        "isLeaf": false,
        "majCode": "4",
        "taskOrder": 3,
        "children": [{
          "id": "779893942852403200-4-14013",
          "taskId": "779893942852403200",
          "zxbNum": 1,
          "struId": "14013",
          "name": "-",
          "orgCode": "9918",
          "isLeaf": true,
          "majCode": "4",
          "taskOrder": 4,
          "children": [],
          "struType": "6"
        }],
        "struType": "5"
      }],
      "struType": "4"
    }],
    "struType": ""
  }],
  "msg": "操作成功"
}
JSON

 

2 可以修改ztree的样式。

这个问题就比较复杂了,因为不同的DOM结构,很难保证ztree的样式可以改的和原来的(elementUI)完全一致。

但是至少改一个icon是没啥问题的。

假设我们不喜欢ztree的默认样式,而且想用UI图标库(比如font awasome)去代替原来的图标。

我们可以研究一下原来ztree的样式,然后对症下药去修改。

这个可以看下我最后贴的完整版引用代码。

<template>
  <div id="app" class="flex-col">
    <h1 class="T">
      Vue-Giant-Tree
      <a
        href="https://github.com/tower1229/Vue-Giant-Tree"
        target="_blank"
        titie="Vue-Giant-Tree"
      >
        <svg
          class="octicon octicon-mark-github v-align-middle"
          height="32"
          viewBox="0 0 16 16"
          version="1.1"
          width="16"
          aria-hidden="true"
        >
          <path
            fill-rule="evenodd"
            d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
          />
        </svg>
      </a>
    </h1>

    <div class="wrap flex-1">
      <div id="c" class="c">
        <tree
          :setting="setting"
          :nodes="nodes"
          @onClick="onClick"
          @onCheck="onCheck"
          @onCreated="handleCreated"
        />
      </div>
    </div>

    <div class="toolbar">
      <button class="btn" type="button" @click="update">更新数据</button>
    </div>

    <footer class="foot">
      <p>
        © 2019 - 3019 Author
        <a href="https://refined-x.com/" target="_blank">前端路上</a>
      </p>
    </footer>
  </div>
</template>

<script>
const bigData = require("@/mock/big-tree.json");
// const bigData2 = require("@/mock/tree.json");
// const bigData3 = require("@/mock/json_a.json");
const bigData4 = require("@/mock/taskdata.json");
// const simpleData = [
//   { id: 1, pid: 0, name: "随意勾选 1", open: true },
//   { id: 11, pid: 1, name: "随意勾选 1-1", open: true },
//   { id: 111, pid: 11, name: "随意勾选 1-1-1" },
//   { id: 112, pid: 11, name: "随意勾选 1-1-2" },
//   { id: 12, pid: 1, name: "随意勾选 1-2", open: true },
//   { id: 121, pid: 12, name: "随意勾选 1-2-1" },
//   { id: 122, pid: 12, name: "随意勾选 1-2-2" },
//   { id: 2, pid: 0, name: "随意勾选 2", checked: true, open: true },
//   { id: 21, pid: 2, name: "随意勾选 2-1" },
//   { id: 22, pid: 2, name: "随意勾选 2-2", open: true },
//   { id: 221, pid: 22, name: "随意勾选 2-2-1", checked: true },
//   { id: 222, pid: 22, name: "随意勾选 2-2-2" },
//   { id: 23, pid: 2, name: "随意勾选 2-3" }
// ];
const dataQueue = [bigData.data, bigData4.data];

export default {
  name: "app",
  components: {
    tree: resolve => require(["./components/ztree.vue"], resolve)
  },
  data() {
    return {
      showIndex: 0,
      setting: {
        check: {
          enable: false
        },
        data: {
          simpleData: {
            enable: true,
            pIdKey: "pid"
          }
        }
      }
    };
  },
  computed: {
    nodes: function() {
      return dataQueue[this.showIndex];
    }
  },
  methods: {
    onClick: function(evt, treeId, treeNode) {
      // 点击事件
      console.log(evt.type, treeNode);
    },
    onCheck: function(evt, treeId, treeNode) {
      // 选中事件
      console.log(evt.type, treeNode);
    },
    handleCreated: function(ztreeObj) {
      // onCreated 中操作ztreeObj对象展开第一个节点
      ztreeObj.expandNode(ztreeObj.getNodes()[0], true);
    },
    update: function() {
      // 更新示例数据
      this.showIndex = this.showIndex === 0 ? 1 : 0;
    }
  }
};
</script>

<style>
html,body{height: 100%;}
body {
  margin: 0;
}

/* flex栅格 */
.flex-col {
  overflow: hidden;
  display: -ms-box;
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  -ms-flex-direction: column;
}

.flex-row {
  overflow: hidden;
  display: -ms-box;
  display: -ms-flexbox;
  display: flex;
}

.flex-1 {
  -ms-flex: 1;
  flex: 1;
  min-width: 0;
}

.flex-2 {
  -ms-flex: 2;
  flex: 2;
  min-width: 0;
}

.flex-3 {
  -ms-flex: 3;
  flex: 3;
  min-width: 0;
}

.flex-4 {
  -ms-flex: 4;
  flex: 4;
  min-width: 0;
}

.align-stretch {
  -ms-align-items: stretch;
  -ms-flex-align: stretch;
  align-items: stretch;
}

.align-center {
  -ms-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}

.justify-center {
  -ms-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}

#app {
  height: 100%;
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
.wrap{
  overflow: hidden;
}
.c {
  width: 600px;
  height: 100%;
  overflow: auto;
  margin: auto;
}
.T {
  font-size: 34px;
  margin: 0 0 30px;
  height: 170px;
  line-height: 260px;
  overflow: hidden;
  background:url(./assets/logo.png) center no-repeat;
}
.toolbar {
  margin: 20px auto;
}
.toolbar .btn {
  padding: 0.5em 1em;
  outline: none;
  border-radius: 4px;
}

.foot {
  margin-top: 30px;
  background: #333;
  padding: 24px;
  overflow: hidden;
  color: #999;
  font-size: 14px;
  text-align: center;
}

.foot a {
  color: #fff;
  margin: 0 0.5em;
}

#c .ztree .button.noline_close:before, 
#c .ztree .button.noline_open:before, 
#c .ztree .button.root_open:before, 
#c .ztree .button.root_close:before, 
#c .ztree .button.roots_open:before, 
#c .ztree .button.roots_close:before, 
#c .ztree .button.bottom_open:before, 
#c .ztree .button.bottom_close:before, 
#c .ztree .button.center_open:before, 
#c .ztree .button.center_close:before {
  content: "\f196";
  position: absolute;
  right: 0px;
  top:3px;
  font: normal normal normal 14px/1 FontAwesome;
  font-size: 17px;
  text-rendering: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #999999;
}
#c .ztree .button.noline_open:before, 
#c .ztree .button.root_open:before, 
#c .ztree .button.roots_open:before, 
#c .ztree .button.bottom_open:before, 
#c .ztree .button.center_open:before {
  content: "\f147";
  position: absolute;
  right: 0px;
  top:3px;
  font: normal normal normal 14px/1 FontAwesome;
  font-size: 17px;
  text-rendering: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transform: unset;
  color: #009280;
}
</style>
App.vue

 

posted on 2023-11-25 17:51  fox_charon  阅读(461)  评论(0编辑  收藏  举报

导航