[更新]: 树形组件基础演示

This commit is contained in:
落小梅
2021-10-11 18:09:38 +08:00
parent 71e07cb0ac
commit 0617787e6a
7 changed files with 292 additions and 173 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -12,7 +12,7 @@ export const useTreeData: UseTreeData = (props, emit) => {
}
return getTreeSpreadKeys(props.data)
},
set: (value) => {
set: (value: (string | number)[]) => {
emit('update:spreadKeys', value)
}
})