cloud-ui.vusion
Version:
Vusion Cloud UI
633 lines (576 loc) • 24.2 kB
Markdown
### 基本用法
有两种书写方式,这里推荐使用Data方式,因为树型结构的数据有时非常多。
#### Tag 方式
``` html { width: 30% }
<u-tree-view>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2">
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
```
#### Data 方式
``` html { width: 30% }
<u-tree-view :data="[
{ text: '节点 1', children: [
{ text: '节点 1.1' },
{ text: '节点 1.2', children: [
{ text: '节点 1.2.1' },
{ text: '节点 1.2.2' },
] },
{ text: '节点 1.3' },
{ text: '节点 1.4' },
] },
{ text: '节点 2' },
{ text: '节点 3', children: [
{ text: '节点 3.1' },
{ text: '节点 3.2' },
] },
]"></u-tree-view>
```
#### 自定义模板
Tag 方式很容易自定义模板,而 Data 方式却不好扩展。我们提供了一个名为`text`的作用域插槽,可以很轻松地处理这个问题。
``` html { width: 30% }
<u-tree-view :data="[
{ text: '文件夹1', type: 'directory', children: [
{ text: '文件夹1.1', type: 'directory' },
{ text: '文件夹1.2', type: 'directory', children: [
{ text: '文件1.2.1', type: 'file' },
{ text: '文件1.2.2', type: 'file' },
] },
{ text: '文件1.3', type: 'file' },
{ text: '文件1.4', type: 'file' },
] },
{ text: '文件夹2', type: 'directory' },
{ text: '文件夹3', type: 'directory', children: [
{ text: '文件3.1', type: 'file' },
{ text: '文件3.2', type: 'file' },
] },
]">
<span slot="text" slot-scope="{ node, expanded, text }">
{{ node.type === 'directory' ? (expanded ? '📂' : '📁') : '📄' }}
{{ text }}
</span>
</u-tree-view>
```
但`text`作用域插槽只支持扩展 text 文本内容,如果你的需求更加复杂,建议直接通过继承 UTreeView 相关组件来实现。
### 选项值
#### Tag 方式
``` html { width: 30% }
<u-tree-view value="1.2">
<u-tree-view-node text="节点 1" value="1">
<u-tree-view-node text="节点 1.1" value="1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2" value="1.2">
<u-tree-view-node text="节点 1.2.1" value="1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2" value="1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3" value="1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4" value="1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2" value="2"></u-tree-view-node>
<u-tree-view-node text="节点 3" value="3">
<u-tree-view-node text="节点 3.1" value="3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2" value="3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
```
#### Data 方式
``` html { width: 30% }
<u-tree-view value="1.2" :data="[
{ text: '节点 1', value: '1', children: [
{ text: '节点 1.1', value: '1.1' },
{ text: '节点 1.2', value: '1.2', children: [
{ text: '节点 1.2.1', value: '1.2.1' },
{ text: '节点 1.2.2', value: '1.2.2' },
] },
{ text: '节点 1.3', value: '1.3' },
{ text: '节点 1.4', value: '1.4' },
] },
{ text: '节点 2', value: '2' },
{ text: '节点 3', value: '3', children: [
{ text: '节点 3.1', value: '3.1' },
{ text: '节点 3.2', value: '3.2' },
] },
]"></u-tree-view>
```
### 只读、禁用、禁用某一项
#### Tag 方式
``` html
<u-grid-layout>
<u-grid-layout-column :span="4">
<u-tree-view readonly>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2">
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
</u-grid-layout-column>
<u-grid-layout-column :span="4">
<u-tree-view disabled>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2">
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
</u-grid-layout-column>
<u-grid-layout-column :span="4">
<u-tree-view>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2" disabled>
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3" disabled></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2" disabled></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
</u-grid-layout-column>
</u-grid-layout>
```
#### Data 方式
``` html { width: 30% }
<u-tree-view :data="[
{ text: '节点 1', children: [
{ text: '节点 1.1' },
{ text: '节点 1.2', disabled: true, children: [
{ text: '节点 1.2.1' },
{ text: '节点 1.2.2'}
] },
{ text: '节点 1.3', disabled: true },
{ text: '节点 1.4' },
] },
{ text: '节点 2', disabled: true },
{ text: '节点 3', children: [
{ text: '节点 3.1' },
{ text: '节点 3.2'}
]}
]"></u-tree-view>
```
### 异步加载
``` vue { width: 30% }
<template>
<u-tree-view :data-source="load" text-field="title"></u-tree-view>
</template>
<script>
// 模拟后端请求
const mockRequest = (data, timeout = 300) => new Promise((res, rej) => setTimeout(() => res(data), timeout));
export default {
methods: {
load(params) {
if (!params.node) {
return mockRequest([
{ type: 'app', title: '应用1', childrenField: 'services' },
{ type: 'app', title: '应用2', childrenField: 'services' },
]);
} else if (params.node.type === 'app') {
return mockRequest([
{ type: 'service', title: '服务1', childrenField: 'pages' },
{ type: 'service', title: '服务2', childrenField: 'pages' },
{ type: 'service', title: '服务3', childrenField: 'pages' },
]);
} else if (params.node.type === 'service') {
return mockRequest([
{ type: 'page', title: '页面1', isLeaf: true, childrenField: 'children' },
{ type: 'page', title: '页面2', isLeaf: true, childrenField: 'children' },
]);
}
},
},
}
</script>
```
### Tag 和 Data 混合
``` vue { width: 30% }
<template>
<u-tree-view :data-source="load" text-field="title">
<u-tree-view-node v-for="app in apps" v-if="app.subType !== 'other'" :text="app.title" :node="app" children-field="services"></u-tree-view-node>
</u-tree-view>
</template>
<script>
// 模拟后端请求
const mockRequest = (data, timeout = 300) => new Promise((res, rej) => setTimeout(() => res(data), timeout));
export default {
data() {
return {
apps: [
{ type: 'app', title: '应用1' },
{ type: 'app', title: '应用2' },
{ type: 'app', title: '应用3', subType: 'other' },
{ type: 'app', title: '应用4' },
],
};
},
methods: {
load(params) {
if (params.node.type === 'app') {
return mockRequest([
{ type: 'service', title: '服务1', childrenField: 'pages' },
{ type: 'service', title: '服务2', childrenField: 'pages' },
{ type: 'service', title: '服务3', childrenField: 'pages' },
]);
} else if (params.node.type === 'service') {
return mockRequest([
{ type: 'page', title: '页面1' },
{ type: 'page', title: '页面2' },
]);
} else {
return mockRequest();
}
},
},
}
</script>
```
### 字段路径
``` vue { width: 30% }
<template>
<u-tree-view :data-source="load" text-field="title"></u-tree-view>
</template>
<script>
// 模拟后端请求
const mockRequest = (data, timeout = 300) => new Promise((res, rej) => setTimeout(() => res(data), timeout));
export default {
methods: {
load(params) {
if (!params.node) {
return mockRequest([
{ type: 'app', title: '应用1', childrenField: 'services' },
{ type: 'app', title: '应用2', childrenField: 'services' },
]);
} else if (params.node.type === 'app') {
return mockRequest([
{ type: 'service', title: '服务1', front: {}, childrenField: 'front.pages' },
{ type: 'service', title: '服务2', front: {}, childrenField: 'front.pages' },
{ type: 'service', title: '服务3', front: {}, childrenField: 'front.pages' },
]);
} else if (params.node.type === 'service') {
return mockRequest([
{ type: 'page', title: '页面1', isLeaf: true, childrenField: 'children' },
{ type: 'page', title: '页面2', isLeaf: true, childrenField: 'children' },
]);
}
},
},
}
</script>
```
### 手风琴
``` html { width: 30% }
<u-tree-view accordion>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1">
<u-tree-view-node text="节点 1.1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.1.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.2">
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3">
<u-tree-view-node text="节点 1.3.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.3.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2" expanded>
<u-tree-view-node text="节点 2.1"></u-tree-view-node>
<u-tree-view-node text="节点 2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
```
### 展开/折叠触发方式
``` html
<u-grid-layout>
<u-grid-layout-column :span="4" expand-trigger="click">
<p>整行点击均可触发(默认)</p>
<u-tree-view>
<u-tree-view-node text="节点 1" expanded>
<u-tree-view-node text="节点 1.1" expanded></u-tree-view-node>
<u-tree-view-node text="节点 1.2" expanded>
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
</u-grid-layout-column>
<u-grid-layout-column :span="4">
<p>仅点击小箭头时触发</p>
<u-tree-view expand-trigger="click-expander">
<u-tree-view-node text="节点 1" expanded>
<u-tree-view-node text="节点 1.1" expanded></u-tree-view-node>
<u-tree-view-node text="节点 1.2" expanded>
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
</u-grid-layout-column>
</u-grid-layout>
```
### 可取消
``` html { width: 30% }
<u-tree-view cancelable>
<u-tree-view-node text="节点 1">
<u-tree-view-node text="节点 1.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2">
<u-tree-view-node text="节点 1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点 1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 1.3"></u-tree-view-node>
<u-tree-view-node text="节点 1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点 2"></u-tree-view-node>
<u-tree-view-node text="节点 3">
<u-tree-view-node text="节点 3.1"></u-tree-view-node>
<u-tree-view-node text="节点 3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
```
### 节点显示/隐藏
Tag 方式中可以使用`v-show`,Data 方式中可以使用`hidden`属性
``` html { width: 30% }
<u-tree-view cancelable>
<u-tree-view-node v-show="false" text="节点1">
<u-tree-view-node text="节点1.1"></u-tree-view-node>
<u-tree-view-node text="节点1.2">
<u-tree-view-node text="节点1.2.1"></u-tree-view-node>
<u-tree-view-node text="节点1.2.2"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点1.3"></u-tree-view-node>
<u-tree-view-node text="节点1.4"></u-tree-view-node>
</u-tree-view-node>
<u-tree-view-node text="节点2"></u-tree-view-node>
<u-tree-view-node text="节点3">
<u-tree-view-node text="节点3.1" hidden></u-tree-view-node>
<u-tree-view-node text="节点3.2"></u-tree-view-node>
</u-tree-view-node>
</u-tree-view>
```
### 多选
通过`checkable`属性开启多选模式。
控制多选有两种方式,一种是设置数据各项的`checked`属性,该属性会与多项选择框进行双向绑定。`disabled`属性可以禁用多项选择框。
``` vue { width: 30% }
<template>
<u-tree-view ref="treeView" checkable :data="data"></u-tree-view>
</template>
<script>
export default {
data() {
return {
data: [
{ text: '节点 1', expanded: true, checked: false, children: [
{ text: '节点 1.1', expanded: false, checked: false },
{ text: '节点 1.2', expanded: true, checked: false, children: [
{ text: '节点 1.2.1', expanded: false, checked: false },
{ text: '节点 1.2.2', expanded: false, checked: false },
] },
{ text: '节点 1.3', expanded: false, checked: false },
{ text: '节点 1.4', expanded: false, checked: false },
] },
{ text: '节点 2', expanded: false, checked: false },
{ text: '节点 3', expanded: false, checked: false },
],
};
},
};
</script>
```
另一种是通过`:values.sync`对选择值进行双向绑定,该方法要求每项有`value`作为唯一值。`values`只会收集叶子节点的值。
``` vue { width: 30% }
<template>
<u-tree-view ref="treeView" checkable :values.sync="values" :data="data"></u-tree-view>
</template>
<script>
export default {
data() {
return {
values: ['1.2.1', '1.2.2', '1.3', '3'],
data: [
{ text: '节点 1', value: '1', expanded: true, checked: false, children: [
{ text: '节点 1.1', value: '1.1', expanded: false, checked: false },
{ text: '节点 1.2', value: '1.2', expanded: true, checked: false, children: [
{ text: '节点 1.2.1', value: '1.2.1', expanded: false, checked: false },
{ text: '节点 1.2.2', value: '1.2.2', expanded: false, checked: false },
] },
{ text: '节点 1.3', value: '1.3', expanded: false, checked: false },
{ text: '节点 1.4', value: '1.4', expanded: false, checked: false },
] },
{ text: '节点 2', value: '2', expanded: false, checked: false },
{ text: '节点 3', value: '3', expanded: false, checked: false },
],
};
},
};
</script>
```
通过 `check-controlled` 属性开启节点状态完全受控,父子不关联。
``` vue { width: 30% }
<template>
<u-tree-view ref="treeView" check-controlled checkable :values.sync="values" :data="data"></u-tree-view>
</template>
<script>
export default {
data() {
return {
values: ['1', '1.2', '1.2.1', '1.2.2'],
data: [
{ text: '节点 1', value: '1', expanded: true, checked: false, children: [
{ text: '节点 1.1', value: '1.1', expanded: false, checked: false },
{ text: '节点 1.2', value: '1.2', expanded: true, checked: false, children: [
{ text: '节点 1.2.1', value: '1.2.1', expanded: false, checked: false },
{ text: '节点 1.2.2', value: '1.2.2', expanded: false, checked: false },
] },
{ text: '节点 1.3', value: '1.3', expanded: false, checked: false },
{ text: '节点 1.4', value: '1.4', expanded: false, checked: false },
] },
{ text: '节点 2', value: '2', expanded: false, checked: false },
{ text: '节点 3', value: '3', expanded: false, checked: false },
],
};
},
};
</script>
```
### 其他方法
#### 统一操作
UTreeView 有针对选中/取消和展开/收起两个操作的统一处理的方法:`checkAll`和`toggleAll`,方便开发者使用。
``` vue { width: 30% }
<template>
<u-linear-layout direction="vertical">
<u-tree-view ref="treeView" checkable :data="data"></u-tree-view>
<u-linear-layout>
<u-button @click="checkAll(true)">全部选中</u-button>
<u-button @click="checkAll(false)">全部取消</u-button>
<u-button @click="toggleAll(true)">全部展开</u-button>
<u-button @click="toggleAll(false)">全部收起</u-button>
</u-linear-layout>
</u-linear-layout>
</template>
<script>
export default {
data() {
return {
data: [
{ text: '节点 1', expanded: true, checked: false, children: [
{ text: '节点 1.1', expanded: false, checked: false },
{ text: '节点 1.2', expanded: true, checked: false, disabled: true, children: [
{ text: '节点 1.2.1', expanded: false, checked: false },
{ text: '节点 1.2.2', expanded: false, checked: false },
] },
{ text: '节点 1.3', expanded: false, checked: false },
{ text: '节点 1.4', expanded: false, checked: false },
] },
{ text: '节点 2', expanded: false, checked: false },
{ text: '节点 3', expanded: false, checked: false },
],
};
},
methods: {
checkAll(checked) {
this.$refs.treeView.checkAll(checked);
},
toggleAll(expanded) {
this.$refs.treeView.toggleAll(expanded);
},
},
};
</script>
```
#### 遍历和查找
UTreeView 有关于遍历与查找节点的方法:`walk`和`find`,方便开发者使用。
``` vue { width: 30% }
<template>
<u-linear-layout direction="vertical">
<u-tree-view ref="treeView" :data="data"></u-tree-view>
<u-linear-layout>
<u-button @click="walk()">遍历所有节点</u-button>
<u-button @click="find()">查找末尾为`4`的节点</u-button>
</u-linear-layout>
</u-linear-layout>
</template>
<script>
export default {
data() {
return {
data: [
{ text: '节点 1', expanded: true, checked: false, children: [
{ text: '节点 1.1', expanded: false, checked: false },
{ text: '节点 1.2', expanded: true, checked: false, disabled: true, children: [
{ text: '节点 1.2.1', expanded: false, checked: false },
{ text: '节点 1.2.2', expanded: false, checked: false },
] },
{ text: '节点 1.3', expanded: false, checked: false },
{ text: '节点 1.4', expanded: false, checked: false },
] },
{ text: '节点 2', expanded: false, checked: false },
{ text: '节点 3', expanded: false, checked: false },
],
};
},
methods: {
walk() {
// 注意:如果有返回值,遍历会终止。
this.$refs.treeView.walk((nodeVM) => console.info(nodeVM.text));
},
find() {
const nodeVM = this.$refs.treeView.find((nodeVM) => nodeVM.text.endsWith('4'));
alert(nodeVM.text);
},
},
};
</script>
```