Skip to content

Commit

Permalink
v1.3.3 增加异步加载错误处理 && 虚拟列表时平铺tree数据
Browse files Browse the repository at this point in the history
  • Loading branch information
jingyu.yang committed Jul 6, 2020
1 parent 2c6be26 commit 6a726bc
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 88 deletions.
37 changes: 30 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
# vs-tree

> 项目改与: [element-ui](https://element.eleme.cn/#/zh-CN/component/tree);<br />
> 虚拟列表使用: [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list);
一个基于 vue 的 通用tree组件,支持层级面包屑、虚拟滚动、懒加载、最大可选,复选框...

## 具有和element-ui tree组件所有功能另添加面包屑和虚拟列表

## 浏览器支持

![Edge](https://raw.github.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ |

## 功能点

* [x] 基础树组件
* [x] 层级面包屑
* [x] 复选框
* [x] 异步加载数据/报错处理
* [x] 虚拟列表
* [x] 最大可选

## 基于el-tree新增扩展

简单易用同时满足pc和移动端的Tree结构需求:
详情见: [使用说明](./examples/docs/tree.md).
Expand All @@ -16,11 +31,17 @@

### 安装

`npm install vs-tree`
依赖库:[vue](https://www.npmjs.com/package/vue) 2.5+

```shell
npm install vs-tree
```


`yarn add vs-tree`
```shell
yarn add vs-tree
```

### 使用

Expand Down Expand Up @@ -48,4 +69,6 @@
};
}
}
```
```

> 项目基于: [el-tree](https://element.eleme.cn/#/zh-CN/component/tree); 虚拟列表: [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list);
2 changes: 1 addition & 1 deletion examples/docs/tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,7 @@
| node-key | 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的 | String |||
| props | 配置选项,具体看下表 | object |||
| render-after-expand | 是否在第一次展开某个树节点后才渲染其子节点 | boolean || true |
| load | 加载子树数据的方法,仅当 lazy 属性为true 时生效 | function(node, resolve) |||
| load | 加载子树数据的方法,仅当 lazy 属性为true 时生效 | function(node, resolve, reject) |||
| render-content | 树节点的内容区的渲染 Function | Function(h, { node, data, store } |||
| highlight-current | 是否高亮当前选中节点,默认值是 false。 | boolean || false |
| default-expand-all | 是否默认展开所有节点 | boolean || false |
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vs-tree",
"version": "1.3.2",
"version": "1.3.3",
"description": "vs-tree component for Vue",
"keywords": [
"Organize contacts",
Expand Down
Binary file modified packages/theme-chalk/src/fonts/iconfont.ttf
Binary file not shown.
Binary file modified packages/theme-chalk/src/fonts/iconfont.woff
Binary file not shown.
4 changes: 4 additions & 0 deletions packages/theme-chalk/src/icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
-moz-osx-font-smoothing: grayscale;
}

.vs-icon-warning:before {
content: "\e641";
}

.vs-icon-checkbox:before {
content: "\e604";
}
Expand Down
4 changes: 4 additions & 0 deletions packages/theme-chalk/src/tree.scss
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@
color: $--tree-expand-icon-color;
}

@include e(warn-icon) {
color: $--color-danger;
}

& > .vs-tree-node__children {
overflow: hidden;
background-color: transparent;
Expand Down
56 changes: 14 additions & 42 deletions packages/tree/src/tree-node.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,55 +49,29 @@
v-if="node.loading"
class="vs-tree-node__loading-icon vs-icon-loading">
</span>
<span
v-else-if="node.error"
class="vs-tree-node__warn-icon vs-icon-warning">
</span>
<node-content :node="node"></node-content>
</div>
<vs-collapse-transition v-if="!breadcrumb">
<vs-collapse-transition v-if="!breadcrumb && !virtual">
<div
class="vs-tree-node__children"
v-if="!renderAfterExpand || childNodeRendered"
v-show="expanded"
role="group"
:aria-expanded="expanded"
>
<template v-if="virtual">
<virtual-list
class="vs-virtual-list"
:style="virtualStyle"
:size="nodeHeightSize"
:start="0"
:remain="30"
:bench="30"
>
<vs-tree-node
:render-content="renderContent"
v-for="child in node.childNodes"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(child)"
:node="child"
@node-expand="handleChildNodeExpand">
</vs-tree-node>
</virtual-list>
<!-- <virtual-list
:style="virtualStyle"
:data-key="getNodeKey"
:estimate-size="nodeHeightSize"
:data-sources="node.childNodes"
:extra-props="{showCheckbox, renderContent, renderAfterExpand, handleNodeExpand: handleChildNodeExpand}"
:data-component="VsTteeItem">
</virtual-list> -->
</template>
<template v-else>
<vs-tree-node
:render-content="renderContent"
v-for="child in node.childNodes"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(child)"
:node="child"
@node-expand="handleChildNodeExpand">
</vs-tree-node>
</template>
<vs-tree-node
:render-content="renderContent"
v-for="child in node.childNodes"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(child)"
:node="child"
@node-expand="handleChildNodeExpand">
</vs-tree-node>
</div>
</vs-collapse-transition>
</div>
Expand All @@ -108,7 +82,6 @@
import VsCheckbox from 'vs-tree/packages/checkbox';
import emitter from 'vs-tree/src/mixins/emitter';
import { getNodeKey } from './model/util';
import VsTteeItem from './tree-item.vue';

export default {
name: 'VsTreeNode',
Expand Down Expand Up @@ -168,7 +141,6 @@

data() {
return {
VsTteeItem: VsTteeItem,
tree: null,
expanded: false,
childNodeRendered: false,
Expand Down
114 changes: 77 additions & 37 deletions packages/tree/src/tree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,20 @@
}"
role="tree"
>
<vs-breadcrumb class="vs-tree-breadcrumb" separator-class="vs-icon-arrow-right" :class="[breadcrumbClass]" v-if="breadcrumb && !breadcrumbCustom">
<vs-breadcrumb-item><a @click="onCutCrumb(-1)">根目录</a></vs-breadcrumb-item>
<vs-breadcrumb-item v-for="(item, index) in breadcrumbs" :key="item.id">
<a @click="onCutCrumb(index)">{{item.data[props.label]}}</a>
</vs-breadcrumb-item>
</vs-breadcrumb>
<template v-if="virtual">
<virtual-list
:class="virtualClass"
ref="treeVirtual"
:size="nodeHeightSize"
:remain="30"
:bench="30"
<virtual-list
ref="treeVirtual"
:class="virtualClass"
:size="nodeHeightSize"
:remain="30"
:bench="30"
:start="0"
:item="item"
:itemcount="nodeList.length"
:itemprops="getItemprops"
:scrollelement="scrollelement"
:style="virtualStyle"
>
<vs-tree-node
v-for="node in root.childNodes"
:node="node"
:props="props"
:breadcrumb="breadcrumb"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(node)"
:render-content="renderContent"
@node-expand="handleNodeExpand">
</vs-tree-node>
</virtual-list>
<!-- <virtual-list
ref="treeVirtual"
:style="virtualStyle"
:data-key="getNodeKey"
:data-sources="root.childNodes"
:estimate-size="nodeHeightSize"
:extra-props="{showCheckbox, renderContent, renderAfterExpand, handleNodeExpand}"
:data-component="item">
</virtual-list> -->
/>
</template>
<template v-else>
<vs-tree-node
Expand Down Expand Up @@ -80,16 +56,14 @@
import VsTteeItem from './tree-item.vue';
import emitter from 'vs-tree/src/mixins/emitter';
import { addClass, removeClass } from 'vs-tree/src/utils/dom';
import VsBreadcrumb from 'vs-tree/packages/breadcrumb';
export default {
name: 'VsTree',
mixins: [emitter],
components: {
VsTreeNode,
VsBreadcrumb
VsTreeNode
},
provide() {
Expand All @@ -105,6 +79,7 @@
data() {
return {
list: [],
item: VsTteeItem,
store: null,
root: null,
Expand Down Expand Up @@ -239,6 +214,10 @@
}
},
nodeList() {
return this.breadcrumb ? this.root.childNodes : this.list;
},
treeItemArray() {
return Array.prototype.slice.call(this.treeItems);
},
Expand Down Expand Up @@ -279,6 +258,36 @@
},
methods: {
getItemprops(itemIndex) {
const node = this.nodeList[itemIndex];
return {
key: this.getNodeKey(node),
props: {
showCheckbox: this.showCheckbox,
renderContent: this.renderContent,
renderAfterExpand: this.renderAfterExpand,
handleNodeExpand: this.handleNodeExpand,
index: itemIndex,
source: node
}
};
},
updateList() {
if (this.breadcrumb) return;
const list = [];
const toArr = (data, checked) => {
data.forEach(v => {
list.push(v);
if (v.childNodes) toArr(v.childNodes);
});
};
setTimeout(() => {
toArr(this.root.childNodes, true);
this.list = list.filter(v => (v.parent.expanded || v.level === 1) && v.visible);
}, 50);
},
filter(value) {
if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
this.store.filter(value);
Expand Down Expand Up @@ -377,6 +386,12 @@
},
handleNodeExpand(nodeData, node, instance) {
if (!this.breadcrumb && this.virtual) {
node.childNodes.forEach(v => {
v.visible = true;
});
}
this.updateList();
this.broadcast('VsTreeNode', 'tree-node-expand', node);
this.$emit('node-expand', nodeData, node, instance);
},
Expand Down Expand Up @@ -442,11 +457,23 @@
this.store.setChecked(v, true);
});
}
this.updateList();
node.isLoading = false;
node.isCheckLoading = false;
this.$emit('load-change', data, node);
});
} else {
node.error = true;
}
}, () => {
this.$nextTick(() => {
node.isLoading = false;
node.loading = false;
node.loaded = false;
node.error = true;
});
});
},
onCutCrumb(idx) {
Expand Down Expand Up @@ -512,6 +539,10 @@
this.root = this.store.root;
this.$nextTick(() => {
this.updateList();
});
let dragState = this.dragState;
this.$on('tree-node-drag-start', (event, treeNode) => {
if (typeof this.allowDrag === 'function' && !this.allowDrag(treeNode.node)) {
Expand Down Expand Up @@ -661,6 +692,15 @@
this.forceRender();
}
});
this.$on('node-collapse', (event, node) => {
if (!this.breadcrumb && this.virtual) {
node.childNodes.forEach(v => {
v.visible = false;
});
}
this.updateList();
});
},
mounted() {
Expand Down

0 comments on commit 6a726bc

Please sign in to comment.