layui/src/module/tree/index.vue
2021-10-09 22:19:17 +08:00

347 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { computed, unref, VNode, VNodeChild } from 'vue'
import TreeEntity from './TreeEntity.vue'
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
}
type EditAction = 'add' | 'update' | 'del'
type EditType = boolean | EditAction[]
interface TreeProps {
/**
* 指定唯一的id
*/
id?: string
/**
* 选中的节点
*/
checkedKeys?: any[]
/**
* 展开的节点
*/
spreadKeys?: any[]
/**
* 数据源
*/
data?: TreeData
/**
* 是否显示复选框 默认 false
*/
showCheckbox?: boolean
/**
* 是否开启节点的操作图标。默认 false。
若为 true则默认显示“改删”图标
若为 数组则可自由配置操作图标的显示状态和顺序目前支持的操作图标有add、update、del
edit: ['add', 'update', 'del']
*/
edit?: EditType
/**
* 是否开启手风琴模式,默认 false
*/
accordion?: boolean
/**
* 是否仅允许节点左侧图标控制展开收缩。默认 false即点击节点本身也可控制。若为 true则只能通过节点左侧图标来展开收缩
*/
onlyIconControl?: boolean
/**
* 是否允许点击节点时弹出新窗口跳转。默认 false若开启需在节点数据中设定 link 参数(值为 url 格式
* 废弃:能过事件用户自行控制
*/
isJump?: boolean
/**
* 是否开启连接线。默认 true若设为 false则节点左侧出现三角图标。
*/
showLine?: boolean
/**
* 自定义各类默认文本,目前支持以下设定:
*/
text?: {
/**
* 节点默认名称
*/
defaultNodeName?: () => string | string
/**
* 数据为空时的提示文本
*/
none?: () => string | string | VNode | Element
}
}
interface TreeNode {
/**
* 当前点击的节点数据
*/
data: TreeData
/**
* 节点的展开状态
*/
state: 'open' | 'close' | 'normal'
/**
* 当前节点元素
*/
elem: Element | VNode | VNodeChild
}
interface TreeEmits {
/**
* 节点被点击后触发
* @param e 事件
* @param treeNode
*/
(e: 'on-click', treeNode: TreeNode): void
/**
* 点击复选框时触发
* @param e 事件
* @param treeNode
*/
(e: 'on-check', treeNode: TreeNode): void
/**
* 操作节点的回调
* @param e 事件
* @param treeNode
*/
(e: 'on-operate', treeNode: TreeNode): void
(e: 'update:checkedKeys', keys: any[]): void
(e: 'update:spreadKeys', keys: any[]): void
}
const props = withDefaults(defineProps<TreeProps>(), {
showCheckbox: false,
accordion: false,
onlyIconControl: false,
isJump: false,
showLine: true,
edit: true,
})
// tree wrapper style
const treeWrapperClass = computed(() => {
const { showCheckbox, showLine } = unref(props)
return {
'layui-tree': true,
'layui-form': showCheckbox,
'layui-tree-line': showLine,
}
})
/**
* 按 layui的思路这里改变数据
* @param data
* @param isRootNode
*/
function transformTreeData (data: TreeData[], parentExtend = false, isRootNode = true) {
data.forEach((item, index) => {
item._parentExtend = !parentExtend ? (index + 1) !== data.length: parentExtend
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 lang="ts">
export default {
name: 'LayTree',
}
</script>
<template>
<div :class="treeWrapperClass">
<TreeEntity
v-for="(node) in renderData"
:key="node.id"
:id="node.id"
:node="node"
></TreeEntity>
</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>
<style scoped></style>