[更新]:树形组件基础版

This commit is contained in:
落小梅 2021-10-11 16:17:55 +08:00
parent a1824b2da4
commit 6934b11c46
8 changed files with 422 additions and 316 deletions

View File

@ -5,50 +5,153 @@
:data="data" :data="data"
> >
</lay-tree> </lay-tree>
</template> </template>i
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
const data = ref([{ const data = ref([{
title: '江西' title: '一级1'
,id: 1 ,id: 1
,field: 'name1'
,checked: true
,spread: true
,children: [{ ,children: [{
title: '南昌' title: '二级1-1 可允许跳转'
,id: 1000 ,id: 3
,field: 'name11'
,href: 'https://www.layui.com/'
,children: [{ ,children: [{
title: '青山湖区' title: '三级1-1-3'
,id: 10001 ,id: 23
,field: ''
,children: [{
title: '四级1-1-3-1'
,id: 24
,field: ''
,children: [{
title: '五级1-1-3-1-1'
,id: 30
,field: ''
},{
title: '五级1-1-3-1-2'
,id: 31
,field: ''
}]
}]
},{ },{
title: '高新区' title: '三级1-1-1'
,id: 10002 ,id: 7
,field: ''
,children: [{
title: '四级1-1-1-1 可允许跳转'
,id: 15
,field: ''
,href: 'https://www.layui.com/doc/'
}]
},{
title: '三级1-1-2'
,id: 8
,field: ''
,children: [{
title: '四级1-1-2-1'
,id: 32
,field: ''
}]
}] }]
},{ },{
title: '九江' title: '二级1-2'
,id: 1001 ,id: 4
,spread: true
,children: [{
title: '三级1-2-1'
,id: 9
,field: ''
,disabled: true
},{
title: '三级1-2-2'
,id: 10
,field: ''
}]
},{ },{
title: '赣州' title: '二级1-3'
,id: 1002 ,id: 20
,field: ''
,children: [{
title: '三级1-3-1'
,id: 21
,field: ''
},{
title: '三级1-3-2'
,id: 22
,field: ''
}]
}] }]
},{ },{
title: '广西' title: '一级2'
,id: 2 ,id: 2
,field: ''
,spread: true
,children: [{ ,children: [{
title: '南宁' title: '二级2-1'
,id: 2000 ,id: 5
,field: ''
,spread: true
,children: [{
title: '三级2-1-1'
,id: 11
,field: ''
},{
title: '三级2-1-2'
,id: 12
,field: ''
}]
},{ },{
title: '桂林' title: '二级2-2'
,id: 2001 ,id: 6
,field: ''
,children: [{
title: '三级2-2-1'
,id: 13
,field: ''
},{
title: '三级2-2-2'
,id: 14
,field: ''
,disabled: true
}]
}] }]
},{ },{
title: '陕西' title: '一级3'
,id: 3 ,id: 16
,field: ''
,children: [{ ,children: [{
title: '西安' title: '二级3-1'
,id: 3000 ,id: 17
,field: ''
,fixed: true
,children: [{
title: '三级3-1-1'
,id: 18
,field: ''
},{
title: '三级3-1-2'
,id: 19
,field: ''
}]
},{ },{
title: '延安' title: '二级3-2'
,id: 3001 ,id: 27
,field: ''
,children: [{
title: '三级3-2-1'
,id: 28
,field: ''
},{
title: '三级3-2-2'
,id: 29
,field: ''
}]
}] }]
}]) }])
</script> </script>

View File

@ -4,101 +4,92 @@ export default {
} }
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import { computed, unref, VNode, VNodeChild } from 'vue'
import LayIcon from '../icon' import LayIcon from '../icon'
import { TreeNode } from '/@src/module/tree/tree.type'
interface TreeData {
/**
* 节点唯一索引值用于对指定节点进行各类操作
*/
id: string | number
/**
* 节点标题
*/
title: string | (() => string)
/**
* 节点字段名
*/
field: string | (() => string)
/**
* 子节点支持设定选项同父节点
*/
children: TreeData[]
/**
* 点击节点弹出新窗口对应的 url需开启 isJump 参数
* 废弃通过 on-click事件用户控制
*/
href: string | URL
/**
* 节点是否初始展开默认 false
* 废弃设置 v-model:spreadKeys
*/
spread: boolean
/**
* 节点是否初始为选中状态如果开启复选框的话默认 false
* 废弃设置 v-model:checkedKeys
*/
checked: boolean
/**
* 节点是否为禁用状态默认 false
*/
disabled: boolean
}
interface TreeEntityProps { interface TreeEntityProps {
node: TreeData node: TreeNode
id: string | number }
interface EmitEvent {
(e: 'node-click', node: TreeNode): void
} }
const props = defineProps<TreeEntityProps>() const props = defineProps<TreeEntityProps>()
const emit = defineEmits<EmitEvent>()
/**
* 是否设置短线
* @param node
*/
const renderLineShort = (node: TreeNode): boolean => {
return (
//
node._nextSibling === null &&
node._parentNode &&
//
(node._parentNode._nextSibling === null ||
//线
(node._parentNode._nextSibling && !node._parentNode._nextSibling.children))
)
}
/**
* 展开收起 icon样式
* @param node
*/
const nodeIconType = (node: TreeNode): string => {
return !node.spread ? 'layui-icon-addition' : 'layui-icon-subtraction'
}
function handleNodeClick (node: TreeNode) {
emit('node-click', node)
}
</script> </script>
<template> <template>
<template v-if="node.children && node.children.length > 0"> <template v-if="node.children && node.children.length > 0">
<div <div
class="layui-tree-set" class="layui-tree-set"
:class="{ :class="{
// 'layui-tree-setLineShort': (index + 1) === data.length, 'layui-tree-setLineShort': renderLineShort(node),
'layui-tree-setLineShort': false, 'layui-tree-setHide': !node.parentId,
'layui-tree-setHide': node._isRoot,
}" }"
> >
<!-- {{index}}, {{ data.length }}-->
<div class="layui-tree-entry"> <div class="layui-tree-entry">
<div class="layui-tree-main"> <div class="layui-tree-main" @click="handleNodeClick(node)">
<span <span class="layui-tree-iconClick layui-tree-icon">
class="layui-tree-iconClick layui-tree-icon" <LayIcon :type="nodeIconType(node)"></LayIcon>
>
<LayIcon
type="layui-icon-subtraction"
></LayIcon>
</span> </span>
<span class="layui-tree-txt">{{ node.title }}---{{node._hasChild}}</span> <span class="layui-tree-txt">{{ node.title }}</span>
</div> </div>
</div> </div>
<div <div
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine" class="layui-tree-pack layui-tree-showLine"
style="display: block" style="display: block"
v-show="node.spread"
> >
<LayTreeEntity <LayTreeEntity
v-for="(item, index) in node.children" v-for="(item, index) in node.children"
:key="index" :key="index"
:node="item" :node="item"
:id="item.id" @node-click="handleNodeClick"
></LayTreeEntity> ></LayTreeEntity>
</div> </div>
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div class="layui-tree-set" :class="{'layui-tree-setLineShort': false}"><!-- :class="{'layui-tree-setLineShort': isLast}"--> <div
class="layui-tree-set"
:class="{
'layui-tree-setLineShort': renderLineShort(node),
}"
>
<div class="layui-tree-entry"> <div class="layui-tree-entry">
<div class="layui-tree-main"> <div class="layui-tree-main">
<span <span class="layui-tree-iconClick">
class="layui-tree-iconClick"> <LayIcon type="layui-icon-file"></LayIcon>
<LayIcon
type="layui-icon-file"
></LayIcon>
</span> </span>
<span class="layui-tree-txt">{{ node.title }}, {{node._hasChild}},{{node._parentExtend}}</span> <span class="layui-tree-txt">{{ node.title }}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,8 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, unref, VNode, VNodeChild } from 'vue' import { VNode, VNodeChild } from 'vue'
import TreeEntity from './TreeEntity.vue' import TreeEntity from './TreeEntity.vue'
import { useTreeData } from '/@src/module/tree/useTreeData'
import { TreeNode } from '/@src/module/tree/tree.type'
interface TreeData { type EditAction = 'add' | 'update' | 'del'
type EditType = boolean | EditAction[]
export declare interface TreeData {
/** /**
* 节点唯一索引值用于对指定节点进行各类操作 * 节点唯一索引值用于对指定节点进行各类操作
*/ */
@ -40,27 +46,23 @@ interface TreeData {
disabled: boolean disabled: boolean
} }
type EditAction = 'add' | 'update' | 'del' export declare interface TreeProps {
type EditType = boolean | EditAction[]
interface TreeProps {
/** /**
* 指定唯一的id * 指定唯一的id
*/ */
id?: string key?: string
/** /**
* 选中的节点 * 选中的节点
*/ */
checkedKeys?: any[] checkedKeys?: (string | number)[]
/** /**
* 展开的节点 * 展开的节点
*/ */
spreadKeys?: any[] spreadKeys?: (string | number)[]
/** /**
* 数据源 * 数据源
*/ */
data?: TreeData data?: TreeData[]
/** /**
* 是否显示复选框 默认 false * 是否显示复选框 默认 false
*/ */
@ -100,11 +102,12 @@ interface TreeProps {
/** /**
* 数据为空时的提示文本 * 数据为空时的提示文本
*/ */
none?: () => string | string | VNode | Element none?: (() => string) | string | VNode | Element
} }
} }
interface TreeNode {
export interface EmitData {
/** /**
* 当前点击的节点数据 * 当前点击的节点数据
*/ */
@ -119,27 +122,26 @@ interface TreeNode {
elem: Element | VNode | VNodeChild elem: Element | VNode | VNodeChild
} }
interface TreeEmits { export interface TreeEmits {
/** /**
* 节点被点击后触发 * 节点被点击后触发
* @param e 事件 * @param e 事件
* @param treeNode * @param treeNode
*/ */
(e: 'on-click', treeNode: TreeNode): void (e: 'on-click', treeNode: EmitData): void
/** /**
* 点击复选框时触发 * 点击复选框时触发
* @param e 事件 * @param e 事件
* @param treeNode * @param treeNode
*/ */
(e: 'on-check', treeNode: TreeNode): void (e: 'on-check', treeNode: EmitData): void
/** /**
* 操作节点的回调 * 操作节点的回调
* @param e 事件 * @param e 事件
* @param treeNode * @param treeNode
*/ */
(e: 'on-operate', treeNode: TreeNode): void (e: 'on-operate', treeNode: EmitData): void
(e: 'update:checkedKeys', keys: any[]): void (e: 'update:spreadKeys', spreadKeys: string[]): void
(e: 'update:spreadKeys', keys: any[]): void
} }
const props = withDefaults(defineProps<TreeProps>(), { const props = withDefaults(defineProps<TreeProps>(), {
@ -148,48 +150,21 @@ const props = withDefaults(defineProps<TreeProps>(), {
onlyIconControl: false, onlyIconControl: false,
isJump: false, isJump: false,
showLine: true, showLine: true,
edit: true, edit: () => true,
}) })
// tree wrapper style const emit = defineEmits<TreeEmits>()
const treeWrapperClass = computed(() => {
const { showCheckbox, showLine } = unref(props)
return {
'layui-tree': true,
'layui-form': showCheckbox,
'layui-tree-line': showLine,
}
})
/** const {
* layui的思路这里改变数据 innerTreeData,
* @param data updateInnerTreeData,
* @param isRootNode treeWrapperClass
*/ } = useTreeData(props, emit)
function transformTreeData (data: TreeData[], parentExtend = false, isRootNode = true) {
data.forEach((item, index) => { function handleNodeClick(node: TreeNode) {
item._parentExtend = !parentExtend ? (index + 1) !== data.length: parentExtend updateInnerTreeData(innerTreeData.value, node)
if(isRootNode) {
item._isRoot = true
}
if (item.children) {
item._hasChild = true
transformTreeData(item.children, item._parentExtend, false)
} else {
item._hasChild = false
}
})
} }
const renderData = computed(() => {
const { data } = unref(props)
transformTreeData(data)
console.log(data)
return data
})
console.log(renderData)
</script> </script>
<script lang="ts"> <script lang="ts">
export default { export default {
@ -199,148 +174,11 @@ export default {
<template> <template>
<div :class="treeWrapperClass"> <div :class="treeWrapperClass">
<TreeEntity <TreeEntity
v-for="(node) in renderData" v-for="(node) in innerTreeData"
:key="node.id" :key="node.id"
:id="node.id"
:node="node" :node="node"
@node-click="handleNodeClick"
></TreeEntity> ></TreeEntity>
</div> </div>
<hr />
<div class="layui-tree layui-tree-line" lay-filter="LAY-tree-2">
<div
data-id="1"
class="layui-tree-set layui-tree-setHide layui-tree-spread"
>
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick layui-tree-icon"
><i class="layui-icon layui-icon-subtraction"></i></span
><span class="layui-tree-txt">江西</span>
</div>
</div>
<div
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
style="display: block"
>
<div data-id="1000" class="layui-tree-set layui-tree-spread">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick layui-tree-icon"
><i class="layui-icon layui-icon-subtraction"></i></span
><span class="layui-tree-txt">南昌</span>
</div>
</div>
<div
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
style="display: block"
>
<div data-id="10001" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">青山湖区</span>
</div>
</div>
</div>
<div data-id="10002" class="layui-tree-set layui-tree-setLineShort">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">高新区</span>
</div>
</div>
</div>
</div>
</div>
<div data-id="1001" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">九江</span>
</div>
</div>
</div>
<div data-id="1002" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">赣州</span>
</div>
</div>
</div>
</div>
</div>
<div
data-id="2"
class="layui-tree-set layui-tree-setHide layui-tree-spread"
>
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick layui-tree-icon"
><i class="layui-icon layui-icon-subtraction"></i></span
><span class="layui-tree-txt">广西</span>
</div>
</div>
<div
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
style="display: block"
>
<div data-id="2000" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">南宁</span>
</div>
</div>
</div>
<div data-id="2001" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">桂林</span>
</div>
</div>
</div>
</div>
</div>
<div
data-id="3"
class="layui-tree-set layui-tree-setHide layui-tree-setLineShort layui-tree-spread"
>
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick layui-tree-icon"
><i class="layui-icon layui-icon-subtraction"></i></span
><span class="layui-tree-txt">陕西</span>
</div>
</div>
<div class="layui-tree-pack layui-tree-lineExtend" style="display: block">
<div data-id="3000" class="layui-tree-set">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">西安</span>
</div>
</div>
</div>
<div data-id="3001" class="layui-tree-set layui-tree-setLineShort">
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick"
><i class="layui-icon layui-icon-file"></i></span
><span class="layui-tree-txt">延安</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template> </template>
<style scoped></style> <style scoped></style>

View File

@ -1,14 +0,0 @@
import { TreeEmits, TreeProps } from '/@src/module/tree/type'
export const treeProps = withDefaults(defineProps<TreeProps>(), {
showCheckbox: false,
accordion: false,
onlyIconControl: false,
isJump: false,
showLine: true,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
edit: true
})
export const emit = defineEmits<TreeEmits>()

View File

@ -1,36 +1,45 @@
/** /**
* defineProps * defineProps
* @see https://github.com/vuejs/vue-next/issues/4294
* index.vue内部单独实现一份 * index.vue内部单独实现一份
*/ */
import { VNode, VNodeChild } from 'vue' import { ComputedRef, CSSProperties, Ref, UnwrapRef, VNode, VNodeChild, WritableComputedRef } from 'vue'
import { Nullable, Recordable } from '/@src/module/type'
export interface TreeData { type EditAction = 'add' | 'update' | 'del'
type EditType = boolean | EditAction[]
export declare interface TreeData {
/** /**
* *
*/ */
id: () => (string | number) | string | number id: string | number
/** /**
* *
*/ */
title: (() => string) | string title: string | (() => string)
/** /**
* *
*/ */
field: (() => string) | string field: string | (() => string)
/** /**
* *
*/ */
children: TreeData[] children: TreeData[]
/** /**
* url isJump * url isJump
* on-click事件用户控制
*/ */
href: string | URL href: string | URL
/** /**
* false * false
* v-model:spreadKeys
*/ */
spread: boolean spread: boolean
/** /**
* false * false
* v-model:checkedKeys
*/ */
checked: boolean checked: boolean
/** /**
@ -39,15 +48,23 @@ export interface TreeData {
disabled: boolean disabled: boolean
} }
type EditAction = 'add' | 'update' | 'del' export declare interface TreeProps {
/**
type EditType = boolean | EditAction[] * id
*/
export interface TreeProps { key?: string
/**
*
*/
checkedKeys?: (string | number)[]
/**
*
*/
spreadKeys?: (string | number)[]
/** /**
* *
*/ */
data?: TreeData data?: TreeData[]
/** /**
* false * false
*/ */
@ -69,6 +86,7 @@ export interface TreeProps {
onlyIconControl?: boolean onlyIconControl?: boolean
/** /**
* false link url * false link url
*
*/ */
isJump?: boolean isJump?: boolean
/** /**
@ -86,11 +104,11 @@ export interface TreeProps {
/** /**
* *
*/ */
none?: () => string | string | VNode | Element none?: (() => string) | string | VNode | Element
} }
} }
export interface TreeNode { export interface EmitData {
/** /**
* *
*/ */
@ -111,22 +129,22 @@ export interface TreeEmits {
* @param e * @param e
* @param treeNode * @param treeNode
*/ */
(e: 'on-click', treeNode: TreeNode): void (e: 'on-click', treeNode: EmitData): void
/** /**
* *
* @param e * @param e
* @param treeNode * @param treeNode
*/ */
(e: 'on-check', treeNode: TreeNode): void (e: 'on-check', treeNode: EmitData): void
/** /**
* *
* @param e * @param e
* @param treeNode * @param treeNode
*/ */
(e: 'on-operate', treeNode: TreeNode): void (e: 'on-operate', treeNode: EmitData): void
(e: 'update:spreadKeys', spreadKeys: (string | number)[]): void
} }
export interface TreeExpose { export interface TreeExpose {
/** /**
* *
@ -138,3 +156,22 @@ export interface TreeExpose {
// 设置节点勾选 setChecked 变为v-model控制 // 设置节点勾选 setChecked 变为v-model控制
// 实例重载 reload 变为v-model控制 // 实例重载 reload 变为v-model控制
export interface TreeNode extends TreeData {
parentId: string | number
children: TreeNode[]
_parentNode?: Nullable<TreeNode>
_nextSibling?: Nullable<TreeNode>
_expand?: boolean
}
/** hook type **/
export type UseTreeData = (
props: TreeProps,
emit: TreeEmits
) => {
innerTreeData: Ref<UnwrapRef<TreeData[]>>
spreadKeys: WritableComputedRef<(string | number)[]>
treeWrapperClass: ComputedRef<Recordable>
updateInnerTreeData: (treeData: TreeData[], node: TreeData) => void
}

View File

@ -0,0 +1,85 @@
import { TreeData, TreeNode } from '/@src/module/tree/tree.type'
/**
* parentId
* @param data
* @param parentId
*/
export const generatorTreeData = (data: TreeData[] | TreeNode[], parentId: TreeNode['parentId'] = ''): TreeNode[] => {
const innerTreeData: TreeNode[] = []
const len = data.length
for (let i = 0; i < len; i++) {
const item = data[i]
const inner = {
...item,
parentId: parentId,
spread: item.spread || false
}
if (item.children && item.children.length > 0) {
inner.children = generatorTreeData(item.children, item.id)
}
innerTreeData.push(inner as TreeNode)
}
return innerTreeData
}
/**
* nextSiblingnull
* @param data
*/
export const setNextSiblings = (data: TreeNode[]): void => {
const len = data.length
for (let i = 0; i < len; i++) {
data[i]._nextSibling = (i + 1) < len ? data[i+1] : null
if (data[i].children && data[i].children.length > 0) {
setNextSiblings(data[i].children)
}
}
}
/**
* null
* @param data
* @param parentNode
*/
export const setParentNode = (data: TreeNode[], parentNode?: TreeNode): void => {
const len = data.length
for (let i = 0; i < len; i++) {
data[i]._parentNode = parentNode ? parentNode : null
if (data[i].children && data[i].children.length > 0) {
setParentNode(data[i].children, data[i])
}
}
}
/**
* tree结构
* @param data
*/
export const initialTreeData = (data: TreeData[]): TreeNode[] => {
const innerTree = generatorTreeData(data)
setNextSiblings(innerTree)
setParentNode(innerTree)
return innerTree
}
/**
*
* v-model:spreadKeys
* data.item.spreadKeys
* @param data
*/
export const getTreeSpreadKeys = (data: TreeData[]): (string | number)[] => {
let keys: (string | number) [] = []
const len = data.length
for (let i = 0; i < len; i++) {
const id: number | string = data[i].id
if (data[i].spread) {
keys.push(id)
}
if (data[i].children && data[i].children.length > 0) {
keys = [...keys, ...getTreeSpreadKeys(data[i].children)]
}
}
return keys
}

View File

@ -0,0 +1,60 @@
import { TreeData, UseTreeData } from '/@src/module/tree/tree.type'
import { computed, ref, unref, watch } from 'vue'
import { getTreeSpreadKeys, initialTreeData } from '/@src/module/tree/treeHelper'
import { Recordable } from '/@src/module/type'
export const useTreeData: UseTreeData = (props, emit) => {
const spreadKeys = computed({
get: () => {
if (!props.data) return []
if (props.spreadKeys && props.spreadKeys.length > 0) {
return props.spreadKeys as (string | number)[]
}
return getTreeSpreadKeys(props.data)
},
set: (value) => {
emit('update:spreadKeys', value)
}
})
/**
* data
*/
const innerTreeData = ref<TreeData[]>([])
watch(() => props.data, (treeData) => {
if (treeData) {
innerTreeData.value = initialTreeData(treeData)
}
}, { immediate: true, deep: true })
function updateInnerTreeData(treeData: TreeData[], node: TreeData): void {
for(let i = 0; i <treeData.length; i++) {
if (treeData[i].id === node.id) {
treeData[i].spread = !treeData[i].spread
break
}
if (treeData[i].children && treeData[i].children.length > 0) {
updateInnerTreeData(treeData[i].children, node)
}
}
}
/**
* tree wrapper class
*/
const treeWrapperClass = computed((): Recordable => {
const { showCheckbox, showLine } = unref(props)
return {
'layui-tree': true,
'layui-form': showCheckbox,
'layui-tree-line': showLine,
}
})
return {
spreadKeys,
innerTreeData,
updateInnerTreeData,
treeWrapperClass
}
}

View File

@ -1,4 +1,4 @@
import type { App, DefineComponent } from 'vue' import type { App, DefineComponent, Ref } from 'vue'
export type StringObject = Record<string, unknown> export type StringObject = Record<string, unknown>
export type UnknownObject = Record<string | number, unknown> export type UnknownObject = Record<string | number, unknown>
@ -15,3 +15,9 @@ export interface InstallOptions extends StringObject {
/** Menu Attributes */ /** Menu Attributes */
menu?: null menu?: null
} }
export type Nullable<T> = T | null
export type MaybeRef<T> = Ref<T> | T
export type Recordable = Record<string, any>