Skip to content

LimeTree 树

  • 多层次的结构列表
  • 插件依赖lime-sharedlime-style, lime-checkbox,lime-loading不喜勿下

安装

插件市场入口 导入即可,首次可能需要重新编译,付费组件需要自定义基座

代码演示

基础用法

通过data设置树的节点数据

html
<l-tree 
	:data="data" 
	:default-expanded-keys="defaultExpandedKeys" 
	expand-on-click 
	checkable />
js
function repeat(count : number, value ?: any) : any[] {
	const result : any[] = [];
	for (let i = 0; i < count; i++) {
		result.push(value ?? '');
	}
	return result;
}
function createLabel(level : number) : string {
	if (level == 4)
		return '道生一'
	if (level == 3)
		return '一生二'
	if (level == 2)
		return '二生三'
	if (level == 1)
		return '三生万物'
	return ''
}
function createData(level = 4, baseKey : string = '') : UTSJSONObject[] | null {
	if (level == 0) return null
	return repeat(6 - level, null).map((_, index) : UTSJSONObject => {
		const key = `${baseKey}${level}${index}`
		return {
			label: createLabel(level),
			key,
			children: createData(level - 1, key)
		}
	})
}

const data = ref(createData());
const defaultExpandedKeys = ['40', '41']

自定义 key 和 label 的字段

通过key-field,label-field,children-field设置树节点字段

html
<l-tree 
	:data="customData" 
	:default-expanded-keys="defaultExpandedKeys" 
	key-field="id"
	label-field="name" 
	children-field="items" 
	selectable />
js
function repeat(count : number, value ?: any) : any[] {
	const result : any[] = [];
	for (let i = 0; i < count; i++) {
		result.push(value ?? '');
	}
	return result;
}
function createLabel(level : number) : string {
	if (level == 4)
		return '道生一'
	if (level == 3)
		return '一生二'
	if (level == 2)
		return '二生三'
	if (level == 1)
		return '三生万物'
	return ''
}
function createData(level = 4, baseKey : string = '') : UTSJSONObject[] | null {
	if (level == 0) return null
	return repeat(6 - level, null).map((_, index) : UTSJSONObject => {
		const key = `${baseKey}${level}${index}`
		return {
			name: createLabel(level),
			id: key,
			items: createData(level - 1, key)
		}
	})
}

const data = ref(createData());
const defaultExpandedKeys = ['40', '41']

级联选择

设定 cascade 进行级联选择。

html
<l-tree 
	:data="data" 
	cascade 
	:default-expanded-keys="defaultExpandedKeys"
	:default-checked-keys="defaultCheckedKeys" 
	@checked="updateCheckedKeys" 
	checkable />
js
function repeat(count : number, value ?: any) : any[] {
	const result : any[] = [];
	for (let i = 0; i < count; i++) {
		result.push(value ?? '');
	}
	return result;
}
function createLabel(level : number) : string {
	if (level == 4)
		return '道生一'
	if (level == 3)
		return '一生二'
	if (level == 2)
		return '二生三'
	if (level == 1)
		return '三生万物'
	return ''
}
function createData(level = 4, baseKey : string = '') : UTSJSONObject[] | null {
	if (level == 0) return null
	return repeat(6 - level, null).map((_, index) : UTSJSONObject => {
		const key = `${baseKey}${level}${index}`
		return {
			label: createLabel(level),
			key,
			children: createData(level - 1, key)
		}
	})
}

const data = ref(createData());
const defaultExpandedKeys = ref(['40', '4030', '403020'])
const defaultCheckedKeys = ref(['40302010'])


const updateCheckedKeys = (keys : any[]) => {
	console.log('keys', keys)
}

搜索

树接受 pattern来完成搜索。showIrrelevantNodes可以设置只显搜索节点

html
<input type="text" 
	style="background-color: #eee; padding: 10px; height: 50px;" placeholder="输入节点名称"
	v-model="pattern" />
	
<view style="flex-direction: row; padding: 10px; align-items: center;">
	<switch :checked="showIrrelevantNodes" @change="switch2Change"/>
	<text v-show="!showIrrelevantNodes">隐藏搜索无关的节点</text>
	<text v-show="showIrrelevantNodes">显示所有节点</text>
</view>

<l-tree 
	:data="searchData" 
	expandOnClick 
	cascade 
	:pattern="pattern"
	:allow-checking-not-loaded="true"
	:showIrrelevantNodes="showIrrelevantNodes">
</l-tree>
js
const showIrrelevantNodes = ref(false)
const pattern = ref('')
const searchData = [
	{
		label: '0',
		key: '0',
		children: [
			{
				label: '0-0',
				key: '0-0',
				children: [
					{ label: '0-0-0', key: '0-0-0' },
					{ label: '0-0-1', key: '0-0-1' }
				]
			},
			{
				label: '0-1',
				key: '0-1',
				children: [
					{ label: '0-1-0', key: '0-1-0' },
					{ label: '0-1-1', key: '0-1-1' }
				]
			}
		]
	},
	{
		label: '1',
		key: '1',
		children: [
			{
				label: '1-0',
				key: '1-0',
				children: [
					{ label: '1-0-0', key: '1-0-0' },
					{ label: '1-0-1', key: '1-0-1' }
				]
			},
			{
				label: '1-1',
				key: '1-1',
				children: [
					{ label: '1-1-0', key: '1-1-0' },
					{ label: '1-1-1', key: '1-1-1' }
				]
			}
		]
	}
]


const switch2Change = (event : UniSwitchChangeEvent) => {
	showIrrelevantNodes.value = event.detail.value
}

异步加载

使用 load-node 回调来加载数据。异步加载时,所有 isLeaffalse 并且 children 不为数组的节点会被视为未加载的节点。

html
<l-tree 
	loadingColor="red"
	:data="asyncData" 
	cascade 
	:checked-keys="checkedKeys" 
	:expanded-keys="expandedKeys"
	:load-node="handleLoad"
	:allowCheckingNotLoaded="true"
	@checked="handleCheckedKeysChange" 
	@expanded="handleExpandedKeysChange" 
	checkable />
js
function nextLabel(currentLabel ?: any) : string {
	if (currentLabel == null)
		return 'Out of Tao, One is born'
	if (currentLabel == 'Out of Tao, One is born')
		return 'Out of One, Two'
	if (currentLabel == 'Out of One, Two')
		return 'Out of Two, Three'
	if (currentLabel == 'Out of Two, Three') {
		return 'Out of Three, the created universe'
	}
	if (currentLabel == 'Out of Three, the created universe') {
		return 'Out of Tao, One is born'
	}
	if (currentLabel != null) {
		return `${currentLabel}`
	}
	return ''
}
function createData() : UTSJSONObject[] {
	return [
		{
			label: nextLabel(null),
			key: 1,
			isLeaf: false
		},
		{
			label: nextLabel(null),
			key: 2,
			isLeaf: false
		}
	]
}

const expandedKeys = ref<string[]>([])
const checkedKeys = ref<string[]>([])
const asyncData = ref(createData())

const handleLoad = (node : UTSJSONObject) : Promise<boolean> => {
	return new Promise<boolean>((resolve) => {
		setTimeout(() => {
			console.log(`node['label']`, node['label'])
			node.children = [
				{
					label: nextLabel(node['label']),
					key: `${node['key']}${nextLabel(node['label'])}`,
					isLeaf: false
				}
			]
			resolve(true)
		}, 1000)
	})
}

const handleExpandedKeysChange = (keys : string[]) => {
	console.log('handleExpandedKeysChange keys', keys)
	expandedKeys.value = keys
}
const handleCheckedKeysChange = (keys : string[]) => {
	console.log('handleCheckedKeysChange', keys)
	checkedKeys.value = keys
}

自定义内容

可以通过switcher插槽设置展开收缩的图标,content插槽自定义内容,导出的node为节点原始数据。

html
<l-tree 
	:data="data"  
	checkboxPlacement="right"
	expand-on-click 
	center
	checkedColor="red"
	@click="onClick"
	checkable >
	<template #switcher="{expanded}">
		<text v-show="expanded">🤔</text>
		<text v-show="!expanded">🐱</text>
	</template>
	<template #content="{node}">
		<view style="flex-direction: row; align-items: center;">
			<image class="logo" style="width: 30px; height: 30px;" src="https://img-cdn-tc.dcloud.net.cn/uploads/avatar/000/12/54/99_avatar_max.jpg?=1615885669"></image>
			<text style="padding: 10px;">{{node['label']}}公司</text>
		</view>
	</template>
</l-tree>
js
function repeat(count : number, value ?: any) : any[] {
	const result : any[] = [];
	for (let i = 0; i < count; i++) {
		result.push(value ?? '');
	}
	return result;
}
function createLabel(level : number) : string {
	if (level == 4)
		return '道生一'
	if (level == 3)
		return '一生二'
	if (level == 2)
		return '二生三'
	if (level == 1)
		return '三生万物'
	return ''
}
function createData(level = 4, baseKey : string = '') : UTSJSONObject[] | null {
	if (level == 0) return null
	return repeat(6 - level, null).map((_, index) : UTSJSONObject => {
		const key = `${baseKey}${level}${index}`
		return {
			label: createLabel(level),
			key,
			children: createData(level - 1, key)
		}
	})
}

const data = ref(createData());

查看示例

  • 导入后直接使用这个标签查看演示效果
html
 // 代码位于 uni_modules/lime-tree/compoents/lime-tree 
<lime-tree />

插件标签

  • 默认 l-tree 为 component
  • 默认 lime-tree 为 demo

关于vue2的使用方式

  • 插件使用了composition-api, 如果你希望在vue2中使用请按官方的教程vue-composition-api配置
  • 关键代码是: 在main.js中 在vue2部分加上这一段即可.
js
// vue2
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)

API

Props

参数说明类型默认值
cascade是否关联选项booleanfalse
checkStrategy设置勾选策略来指定勾选回调返回的值,all 表示回调函数值为全部选中节点;parent 表示回调函数值为父节点(当父节点下所有子节点都选中时);child 表示回调函数值为子节点stringall
checkable是否显示选择框booleanfalse
checkboxPlacement复选框的位置, 可选值:'left' 'right'stringleft
childrenField替代 TreeOption 中的 children 字段名stringchildren
keyField替代 TreeOption 中的 key 字段名stringkey
labelField替代 TreeOption 中的 label 字段名stringlabel
disabledField替代 TreeOption 中的 disabled 字段名stringdisabled
checkedKeys受控的选中多选项string | number-
data树节点数据Object[]-
defaultCheckedKeys默认选中多选项(string | number)[]-
defaultExpandedKeys默认展开项(string | number)[]-
expandedKeys受控的展开项(string | number)[]-
expandOnClick允许点击节点展开/收缩booleanfalse
checkOnClick允许点击节点勾选booleanfalse
loadNode异步加载回调(node: Object) => Promise<boolean>``
pattern搜索内容string``
showIrrelevantNodes搜索时显示无关节点booleantrue
allowCheckingNotLoaded允许勾选未加载节点booleanfalse
indentWidth缩进宽度number24
center节点内容垂直居中booleanfalse
loadingColorloading颜色string-
checkedColorcheckebox选中颜色string-
rotatableSwitchercheckebox选中颜色booleanfalse

Events

事件名说明回调参数
update:checked-keys勾选触发(keys: Key[])
checked勾选触发(keys: Key[])
update:expanded-keys展开触发(keys: Key[])
expanded展开触发(keys: Key[])
click点击触发(node: object, siblings: object[])

Slots

名称说明
switcher展开收缩图标插槽: { hide : boolean, loading: boolean, expanded: boolean}
content节点内容插槽: { node : Object }

打赏

如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。

源代码

组件源码