[更新]: 树形组件基础演示
This commit is contained in:
@@ -7,8 +7,9 @@ export default {
|
||||
import LayIcon from '../icon'
|
||||
import { TreeNode } from '/@src/module/tree/tree.type'
|
||||
|
||||
interface TreeEntityProps {
|
||||
interface TreeEntityProps{
|
||||
node: TreeNode
|
||||
onlyIconControl: boolean
|
||||
}
|
||||
|
||||
interface EmitEvent {
|
||||
@@ -31,7 +32,7 @@ const renderLineShort = (node: TreeNode): boolean => {
|
||||
(node._parentNode._nextSibling === null ||
|
||||
//上一层父级有延伸线
|
||||
(node._parentNode._nextSibling && !node._parentNode._nextSibling.children))
|
||||
)
|
||||
) as boolean
|
||||
}
|
||||
/**
|
||||
* 展开收起 icon样式
|
||||
@@ -41,10 +42,22 @@ const nodeIconType = (node: TreeNode): string => {
|
||||
return !node.spread ? 'layui-icon-addition' : 'layui-icon-subtraction'
|
||||
}
|
||||
|
||||
/**
|
||||
* 发射至外层
|
||||
* @param node
|
||||
*/
|
||||
function handleNodeClick (node: TreeNode) {
|
||||
emit('node-click', node)
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归事件
|
||||
* @param node
|
||||
*/
|
||||
function innerClick (node: TreeNode) {
|
||||
emit('node-click', node)
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<template v-if="node.children && node.children.length > 0">
|
||||
@@ -56,9 +69,9 @@ function handleNodeClick (node: TreeNode) {
|
||||
}"
|
||||
>
|
||||
<div class="layui-tree-entry">
|
||||
<div class="layui-tree-main" @click="handleNodeClick(node)">
|
||||
<div class="layui-tree-main" @click.prevent.stop="!onlyIconControl && handleNodeClick(node)">
|
||||
<span class="layui-tree-iconClick layui-tree-icon">
|
||||
<LayIcon :type="nodeIconType(node)"></LayIcon>
|
||||
<LayIcon :type="nodeIconType(node)" @click.prevent.stop="handleNodeClick(node)"></LayIcon>
|
||||
</span>
|
||||
<span class="layui-tree-txt">{{ node.title }}</span>
|
||||
</div>
|
||||
@@ -72,7 +85,8 @@ function handleNodeClick (node: TreeNode) {
|
||||
v-for="(item, index) in node.children"
|
||||
:key="index"
|
||||
:node="item"
|
||||
@node-click="handleNodeClick"
|
||||
@node-click="innerClick"
|
||||
:onlyIconControl="onlyIconControl"
|
||||
></LayTreeEntity>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,9 +99,9 @@ function handleNodeClick (node: TreeNode) {
|
||||
}"
|
||||
>
|
||||
<div class="layui-tree-entry">
|
||||
<div class="layui-tree-main">
|
||||
<div class="layui-tree-main" @click.prevent.stop="!onlyIconControl && handleNodeClick(node)">
|
||||
<span class="layui-tree-iconClick">
|
||||
<LayIcon type="layui-icon-file"></LayIcon>
|
||||
<LayIcon type="layui-icon-file" @click.prevent.stop="handleNodeClick(node)"></LayIcon>
|
||||
</span>
|
||||
<span class="layui-tree-txt">{{ node.title }}</span>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import Component from './index.vue'
|
||||
import type { IDefineComponent } from '../type/index'
|
||||
|
||||
Component.install = (app: App) => {
|
||||
app.component(Component.name || 'LayTree', Component)
|
||||
app.component(Component.name || 'LayTree', Component)
|
||||
}
|
||||
|
||||
export default Component as IDefineComponent
|
||||
|
||||
@@ -3,12 +3,13 @@ import { VNode, VNodeChild } from 'vue'
|
||||
import TreeEntity from './TreeEntity.vue'
|
||||
import { useTreeData } from '/@src/module/tree/useTreeData'
|
||||
import { TreeNode } from '/@src/module/tree/tree.type'
|
||||
import { getEmitNode } from '/@src/module/tree/treeHelper'
|
||||
|
||||
type EditAction = 'add' | 'update' | 'del'
|
||||
|
||||
type EditType = boolean | EditAction[]
|
||||
|
||||
export declare interface TreeData {
|
||||
interface TreeData {
|
||||
/**
|
||||
* 节点唯一索引值,用于对指定节点进行各类操作
|
||||
*/
|
||||
@@ -107,40 +108,42 @@ export declare interface TreeProps {
|
||||
}
|
||||
|
||||
|
||||
export interface EmitData {
|
||||
interface EmitData {
|
||||
/**
|
||||
* 当前点击的节点数据
|
||||
*/
|
||||
data: TreeData
|
||||
/**
|
||||
* 节点的展开状态
|
||||
* remove
|
||||
*/
|
||||
state: 'open' | 'close' | 'normal'
|
||||
state?: 'open' | 'close' | 'normal'
|
||||
/**
|
||||
* 当前节点元素
|
||||
* remove
|
||||
*/
|
||||
elem: Element | VNode | VNodeChild
|
||||
elem?: Element | VNode | VNodeChild
|
||||
}
|
||||
|
||||
export interface TreeEmits {
|
||||
interface TreeEmits {
|
||||
/**
|
||||
* 节点被点击后触发
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-click', treeNode: EmitData): void
|
||||
(e: 'node-click', treeNode: EmitData): void
|
||||
/**
|
||||
* 点击复选框时触发
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-check', treeNode: EmitData): void
|
||||
/**
|
||||
* 操作节点的回调
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-operate', treeNode: EmitData): void
|
||||
(e: 'node-check', treeNode: EmitData): void
|
||||
// /**
|
||||
// * 操作节点的回调
|
||||
// * @param e 事件
|
||||
// * @param treeNode
|
||||
// */
|
||||
// (e: 'node-operate', treeNode: EmitData): void
|
||||
(e: 'update:spreadKeys', spreadKeys: string[]): void
|
||||
}
|
||||
|
||||
@@ -163,6 +166,8 @@ const {
|
||||
|
||||
function handleNodeClick(node: TreeNode) {
|
||||
updateInnerTreeData(innerTreeData.value, node)
|
||||
const emitNode = getEmitNode(props.data!, node)
|
||||
emit('node-click', { data: emitNode! })
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -177,6 +182,7 @@ export default {
|
||||
v-for="(node) in innerTreeData"
|
||||
:key="node.id"
|
||||
:node="node"
|
||||
:onlyIconControl="onlyIconControl"
|
||||
@node-click="handleNodeClick"
|
||||
></TreeEntity>
|
||||
</div>
|
||||
|
||||
@@ -116,32 +116,37 @@ export interface EmitData {
|
||||
/**
|
||||
* 节点的展开状态
|
||||
*/
|
||||
state: 'open' | 'close' | 'normal'
|
||||
state?: 'open' | 'close' | 'normal'
|
||||
/**
|
||||
* 当前节点元素
|
||||
*/
|
||||
elem: Element | VNode | VNodeChild
|
||||
elem?: Element | VNode | VNodeChild
|
||||
}
|
||||
|
||||
export interface TreeEmits {
|
||||
export declare interface TreeEmits {
|
||||
/**
|
||||
* 节点被点击后触发
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-click', treeNode: EmitData): void
|
||||
(e: 'node-click', treeNode: EmitData): void
|
||||
/**
|
||||
* 点击复选框时触发
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-check', treeNode: EmitData): void
|
||||
(e: 'node-check', treeNode: EmitData): void
|
||||
/**
|
||||
* 操作节点的回调
|
||||
* @param e 事件
|
||||
* @param treeNode
|
||||
*/
|
||||
(e: 'on-operate', treeNode: EmitData): void
|
||||
// (e: 'on-operate', treeNode: EmitData): void
|
||||
/**
|
||||
* update:spreadKeys
|
||||
* @param e
|
||||
* @param spreadKeys
|
||||
*/
|
||||
(e: 'update:spreadKeys', spreadKeys: (string | number)[]): void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TreeData, TreeNode } from '/@src/module/tree/tree.type'
|
||||
import { Nullable } from '/@src/module/type'
|
||||
|
||||
/**
|
||||
* 添加父级parentId
|
||||
@@ -83,3 +84,26 @@ export const getTreeSpreadKeys = (data: TreeData[]): (string | number)[] => {
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取点击的原数据的节点
|
||||
* @param data
|
||||
* @param node
|
||||
*/
|
||||
export const getEmitNode = (data: TreeData[], node: TreeNode): Nullable<TreeData> => {
|
||||
let item: Nullable<TreeData> = null
|
||||
const len = data.length
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (data[i].id === node.id) {
|
||||
item = data[i]
|
||||
break
|
||||
}
|
||||
if (data[i].children && data[i].children.length > 0) {
|
||||
item = getEmitNode(data[i].children, node)
|
||||
if (item) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const useTreeData: UseTreeData = (props, emit) => {
|
||||
}
|
||||
return getTreeSpreadKeys(props.data)
|
||||
},
|
||||
set: (value) => {
|
||||
set: (value: (string | number)[]) => {
|
||||
emit('update:spreadKeys', value)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user