一,安装与下载
- npm:
$ npm install liquor-tree
- Yarn:
$ yarn add liquor-tree
import Vue from 'Vue' import LiquorTree from 'liquor-tree' // global registration Vue.use(LiquorTree)
二,引用
<template>
<div class="commonTreeSelect">
<van-field
readonly
:label="config.label"
:placeholder="config.placeholder"
v-model="showText"
right-icon="arrow"
:rules="config.rules"
:required="config.required"
@click="showPicker = true"
/>
<van-popup v-model="showPicker" position="bottom">
<div class="header-warp">
<div class="header">
<span class="btn" @click="cacelPicker">取消</span>
<span class="btn" @click="confirmPicker">确定</span>
</div>
<van-search class="search-input" v-model="searchVal" placeholder="请输入关键字"/>
</div>
<div class="tree-wrap">
<tree
ref="tree"
v-model="selectedNode"
:autoCheckChildren="false"
:filter="searchVal"
:data="items"
:options="options"
@node:checked="onNodeCheck"
@node:expanded="onNodeExpand"
>
<div slot-scope="{ node }" class="node-container">
<div class="node-text">{{ node.text }}</div>
<div class="node-controls">
<a href="#" @click.stop="addChildNode(node)">新增</a>
<a href="#" @click.stop="editNode(node)">编辑</a>
<a href="#" @click.stop="removeNode(node)">删除</a>
</div>
</div>
</tree>
</div>
</van-popup>
</div>
</template>
<script>
import Vue from 'vue'
import LiquorTree from 'liquor-tree'
Vue.use(LiquorTree)
export default {
name: 'commonTree',
props: {
config: {
type: Object,
default: () => ({})
}
},
data () {
return {
showText: '',
showPicker: false,
searchVal: '',
items: [
{ id: 0, text: 'Item 1' },
{ id: 1, text: 'Item 2' },
{
id: 2,
text: 'Item 3',
children: [
{ id: 3, text: 'Item 3.1' },
{ id: 4, text: 'Item 3.2' }
]
},
{
id: 5,
text: '园区其他机构',
children: [
{
id: 6,
text: '园区其他机构1',
children: [
{ id: 7, text: '园区其他机构1.1.1园区其他机构1.1.1园区其他机构1.1.1园区其他机构1.1.1园区其他机构1.1.1' },
{ id: 8, text: '园区其他机构1.1.2' },
{ id: 9, text: '园区其他机构1.1.3' }
]
},
{
id: 10,
text: '园区其他机构2',
children: [
{ id: 11, text: '园区其他机构2.1.1' },
{ id: 12, text: '园区其他机构2.1.2' },
{ id: 13, text: '园区其他机构2.1.3' }
]
}
]
}
],
options: {
propertyNames: {
text: 'text',
children: 'children',
state: 'state'
},
filter: {
plainList: true
},
checkbox: true,
checkOnSelect: true,
autoCheckChildren: false
},
selectedNode: null
}
},
methods: {
// 编辑节点
editNode (node, e) {
node.startEditing()
},
// 删除节点
removeNode (node) {
if (confirm('Are you sure?')) {
node.remove()
}
},
// 新增节点
addChildNode (node) {
if (node.enabled()) {
node.append('New Node')
}
},
// 点击展开节点时,只保留一个节点是打开的状态,自动关闭其他打开的节点
onNodeExpand (node) {
const expandedNodes = this.$refs.tree.findAll({ state: { expanded: true } })
expandedNodes.forEach(expandedNode => {
if (expandedNode.id !== node.id && node.depth === expandedNode.depth) {
expandedNode.collapse()
}
})
},
// 取消
cacelPicker () {
this.showText = ''
this.showPicker = false
this.$refs.tree.findAll({ text: /^Java/, state: { checked: false } })
this.$emit('cacelPicker')
},
// 确定
confirmPicker () {
const selection = this.$refs.tree.findAll({ text: /^Java/, state: { disabled: false } })
const textList = selection.tree.checkedNodes.map(v => {
return v.data.text
})
const idList = selection.tree.checkedNodes.map(v => {
return v.id
})
this.showText = textList.length > 0 ? textList.join(',') : ''
const idStr = idList.length > 0 ? idList.join(',') : ''
this.showPicker = false
console.log(1, this.selectedNode)
console.log(2, this.items)
this.$emit('confirmPicker', idStr)
},
onNodeCheck (node) {
console.log(12, node)
}
},
mounted () { }
}
</script>
<style lang="scss" scoped>
.commonTreeSelect{
.header-warp{
width:100%;
.header{
height:40px;
display:flex;
align-items: center;
justify-content: space-between;
font-size:14px;
}
}
/deep/.tree-wrap{
padding-bottom: 10px;
.tree{
max-height: 245px;
overflow-y: auto;
ul{
li{
width:100%;
.tree-checkbox{
width:16px;
height:16px;
}
.tree-anchor{
width:100%;
font-size:14px;
}
.tree-arrow.has-child:after{
width:6px;
height:6px;
}
.tree-checkbox.checked:after{
left: 5px;
top: 1px;
height: 8.5px;
width: 4px;
}
.node-container{
display:flex;
width:100%;
.node-text{
margin-right: 10px;
}
.node-controls{
a{
color: #1989fa;
margin-right: 6px;
}
}
}
}
}
}
}
}
</style>
三,特征:
- drag&drop 拖动及下降
- mobile friendly 移动端友好
- events for every action 每一个操作的事件
- flexible configuration 灵活配置
- any number of instances per page 每页任意数量的实例
- multi selection 多选
- keyboard navigation 键盘导航
- filtering 过滤
- sorting 分选
- integration with Vuex 与vuex集成
四,组件的options属性
### Component Options 组件选项
| 名称 | 类型 | 默认值 | 描述 |
| ---------------- | ---------- | ------- | --------------- |
| multiple | Boolean | true | 允许选择多个节点 |
| checkbox | Boolean | false | 复选框模式,它显示每个节点的复选框 |
| checkOnSelect | Boolean | false | 仅适用于复选框模式。当用户单击文本或者复选框时,节点将处于选中状态。 |
| autoCheckChildren | Boolean | true | 仅适用于复选框模式。子项将与父项具有相同的选中状态 |
| parentSelect | Boolean | false | 通过单击具有子节点的节点,将展开节点。即,我们有两种方法来展开/折叠节点,通过单击箭头和文本 |
| keyboardNavigation | Boolean | true | 允许用户使用键盘导航树 |
| propertyNames | Object | - | 此选项允许重新定义默认树结构 |
| deletion | Boolean | Function | false | 如果keyboardNavigation为false,则忽略此属性。此属性定义删除行为 |
| fetchData | Object | - | 设置异步数据 |
| dnd | Object | - | dnd的事件包括拖动开始,拖动结束 |
| editing | Object | - | 节点的编辑修改,按enter键或者单击页面的任意区域时,更改将被应用。 |
四,Structure结构
{
"id": Number,
"text": String,
"data": Object,
"children": Array,
"state": Object
}
id
: 节点idtext
: 节点labeldata
: 每个节点的中间数据。你想要什么都行。这个对象是为每个节点创建的,VueJS使这个属性反应。children
: 节点子节点state
: 允许用户设置节点的状态。状态包括以下:
{
"selected": false,
"selectable": true,
"checked": false,
"expanded": false,
"disabled": false,
"visible": true,
"indeterminate": false,
"matched": false,
"editable": true,
"dragging": false,
"draggable": true,
"dropable": true
}
附上官网地址:Liquor Tree
评论区求高手列一下适合在移动端使用的其他组件树哦,感谢Thanks♪(・ω・)ノ