feat(tree): add showChecked and wip workspace

This commit is contained in:
落小梅 2021-10-13 15:41:04 +08:00
parent 8b3eaa57c8
commit 75d51b4ff8
6 changed files with 80 additions and 23 deletions

View File

@ -5,10 +5,15 @@
:data="data" :data="data"
:onlyIconControl="iconCtrl" :onlyIconControl="iconCtrl"
:showLine="showLine" :showLine="showLine"
:showCheckbox="showCheckbox"
@node-click="handleClick" @node-click="handleClick"
> >
</lay-tree> </lay-tree>
<br/> <br/>
是否可开启选择框:
<br/>
<lay-switch v-model="showCheckbox"></lay-switch>
<br/>
只能通过节点左侧图标来展开收缩: 只能通过节点左侧图标来展开收缩:
<br/> <br/>
<lay-switch v-model="iconCtrl"></lay-switch> <lay-switch v-model="iconCtrl"></lay-switch>
@ -25,7 +30,7 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue';
const data = ref([ const data = ref([
{ {
@ -215,11 +220,12 @@ const data = ref([
}, },
], ],
}, },
]) ]);
const iconCtrl = ref(false) const iconCtrl = ref(false);
const showLine = ref(true) const showLine = ref(true);
const clickNode = ref(null) const clickNode = ref(null);
const showCheckbox = ref(true);
function handleClick(node) { function handleClick(node) {
clickNode.value = node clickNode.value = node

View File

@ -5,19 +5,23 @@ export default {
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import LayIcon from '../icon' import LayIcon from '../icon'
import LayCheckbox from '../checkbox'
import { TreeNode } from '/@src/module/tree/tree.type' import { TreeNode } from '/@src/module/tree/tree.type'
type EventType = 'icon' | 'node' type EventType = 'icon' | 'node'
interface TreeEntityProps { interface TreeEntityProps {
node: TreeNode node: TreeNode
showCheckbox?: boolean
} }
interface EmitEvent { interface EmitEvent {
(e: 'node-click', node: TreeNode, type: EventType): void (e: 'node-click', node: TreeNode, type: EventType): void
} }
const props = defineProps<TreeEntityProps>() const props = withDefaults(defineProps<TreeEntityProps>(), {
showCheckbox: false,
})
const emit = defineEmits<EmitEvent>() const emit = defineEmits<EmitEvent>()
/** /**
@ -45,7 +49,7 @@ const nodeIconType = (node: TreeNode): string => {
} }
/** /**
* Node Icon Click * 节点Icon点击
* @param node * @param node
*/ */
function handleIconClick(node: TreeNode) { function handleIconClick(node: TreeNode) {
@ -53,7 +57,7 @@ function handleIconClick(node: TreeNode) {
} }
/** /**
* Node Font Click * 节点点击
* @param node * @param node
*/ */
function handleNodeClick(node: TreeNode) { function handleNodeClick(node: TreeNode) {
@ -61,12 +65,15 @@ function handleNodeClick(node: TreeNode) {
} }
/** /**
* 递归事件 * 递归emit事件
* @param node * @param node
* @param type
*/ */
function innerClick(node: TreeNode, type: EventType) { function innerClick(node: TreeNode, type: EventType) {
emit('node-click', node, type) emit('node-click', node, type)
} }
console.log(props.showCheckbox)
</script> </script>
<template> <template>
<template v-if="node.children && node.children.length > 0"> <template v-if="node.children && node.children.length > 0">
@ -85,11 +92,22 @@ function innerClick(node: TreeNode, type: EventType) {
@click.prevent.stop="handleIconClick(node, 'icon')" @click.prevent.stop="handleIconClick(node, 'icon')"
/> />
</span> </span>
<LayCheckbox
v-if="showCheckbox"
name="name"
skin="primary"
label="1"
:checked="true"
>
{{ node.title }}
</LayCheckbox>
<span <span
v-else
class="layui-tree-txt" class="layui-tree-txt"
@click.prevent.stop="handleNodeClick(node, 'node')" @click.prevent.stop="handleNodeClick(node, 'node')"
>{{ node.title }}</span
> >
{{ node.title }}
</span>
</div> </div>
</div> </div>
<div <div
@ -102,6 +120,7 @@ function innerClick(node: TreeNode, type: EventType) {
:key="index" :key="index"
:node="item" :node="item"
@node-click="innerClick" @node-click="innerClick"
:showCheckbox="showCheckbox"
/> />
</div> </div>
</div> </div>
@ -121,11 +140,22 @@ function innerClick(node: TreeNode, type: EventType) {
@click.prevent.stop="handleIconClick(node, 'icon')" @click.prevent.stop="handleIconClick(node, 'icon')"
/> />
</span> </span>
<LayCheckbox
v-if="showCheckbox"
name="name"
skin="primary"
label="1"
:checked="true"
>
{{ node.title }}
</LayCheckbox>
<span <span
v-else
class="layui-tree-txt" class="layui-tree-txt"
@click.prevent.stop="handleNodeClick(node, 'node')" @click.prevent.stop="handleNodeClick(node, 'node')"
>{{ node.title }}</span
> >
{{ node.title }}
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -57,7 +57,7 @@ interface TreeProps {
* 选中的节点 * 选中的节点
*/ */
// eslint-disable-next-line vue/require-default-prop // eslint-disable-next-line vue/require-default-prop
checkedKeys?: (string | number)[] checkedKeys?: NonNullable<(string | number)[]>
/** /**
* 展开的节点 * 展开的节点
*/ */
@ -148,7 +148,8 @@ interface TreeEmits {
// * @param treeNode // * @param treeNode
// */ // */
// (e: 'node-operate', treeNode: EmitData): void // (e: 'node-operate', treeNode: EmitData): void
(e: 'update:spreadKeys', spreadKeys: string[]): void (e: 'update:spreadKeys', spreadKeys: (string | number)[]): void
(e: 'update:checkedKeys', checkedKeys: (string | number)[]): void
} }
const props = withDefaults(defineProps<TreeProps>(), { const props = withDefaults(defineProps<TreeProps>(), {
@ -176,7 +177,7 @@ function handleNodeClick(node: TreeNode, type: 'node' | 'icon') {
} }
// icon emit // icon emit
const emitNode = getEmitNode(props.data!, node) const emitNode = getEmitNode(props.data!, node)
type !== 'icon' && emit('node-click', { data: emitNode! }) type !== 'icon' && emit('node-click', { data: emitNode! })
} }
</script> </script>
<script lang="ts"> <script lang="ts">
@ -191,6 +192,7 @@ export default {
:key="node.id || index" :key="node.id || index"
:node="node" :node="node"
@node-click="handleNodeClick" @node-click="handleNodeClick"
:showCheckbox="showCheckbox"
/> />
</div> </div>
</template> </template>

View File

@ -63,7 +63,7 @@ export declare interface TreeProps {
/** /**
* *
*/ */
checkedKeys?: (string | number)[] checkedKeys?: NonNullable<(string | number)[]>
/** /**
* *
*/ */
@ -155,6 +155,7 @@ export declare interface TreeEmits {
* @param spreadKeys * @param spreadKeys
*/ */
(e: 'update:spreadKeys', spreadKeys: (string | number)[]): void (e: 'update:spreadKeys', spreadKeys: (string | number)[]): void
(e: 'update:checkedKeys', checkedKeys: (string | number)[]): void
} }
export interface TreeExpose { export interface TreeExpose {
@ -182,7 +183,8 @@ export type UseTreeData = (
props: TreeProps, props: TreeProps,
emit: TreeEmits emit: TreeEmits
) => { ) => {
innerTreeData: Ref<UnwrapRef<TreeData[]>> innerTreeData: Ref<UnwrapRef<TreeNode[]>>
checkedKeys: WritableComputedRef<(string | number)[]>
spreadKeys: WritableComputedRef<(string | number)[]> spreadKeys: WritableComputedRef<(string | number)[]>
treeWrapperClass: ComputedRef<Recordable> treeWrapperClass: ComputedRef<Recordable>
updateInnerTreeData: (treeData: TreeData[], node: TreeData) => void updateInnerTreeData: (treeData: TreeData[], node: TreeData) => void

View File

@ -1,14 +1,17 @@
import { TreeData, TreeNode } from '/@src/module/tree/tree.type' import { TreeData, TreeNode } from '/@src/module/tree/tree.type'
import { Nullable } from '/@src/module/type' import { Nullable } from '/@src/module/type'
import { WritableComputedRef } from 'vue'
/** /**
* parentId * parentId
* @param data * @param data
* @param parentId * @param parentId
* @param checkedKeys
*/ */
export const generatorTreeData = ( export const generatorTreeData = (
data: TreeData[] | TreeNode[], data: TreeData[] | TreeNode[],
parentId: TreeNode['parentId'] = '' parentId: TreeNode['parentId'] = '',
checkedKeys: WritableComputedRef<(string | number)[]>
): TreeNode[] => { ): TreeNode[] => {
const innerTreeData: TreeNode[] = [] const innerTreeData: TreeNode[] = []
const len = data.length const len = data.length
@ -20,7 +23,7 @@ export const generatorTreeData = (
spread: item.spread || false, spread: item.spread || false,
} }
if (item.children && item.children.length > 0) { if (item.children && item.children.length > 0) {
inner.children = generatorTreeData(item.children, item.id) inner.children = generatorTreeData(item.children, item.id, checkedKeys)
} }
innerTreeData.push(inner as TreeNode) innerTreeData.push(inner as TreeNode)
} }
@ -62,9 +65,13 @@ export const setParentNode = (
/** /**
* tree结构 * tree结构
* @param data * @param data
* @param checkedKeys
*/ */
export const initialTreeData = (data: TreeData[]): TreeNode[] => { export const initialTreeData = (
const innerTree = generatorTreeData(data) data: TreeData[],
checkedKeys: WritableComputedRef<(string | number)[]>
): TreeNode[] => {
const innerTree = generatorTreeData(data, '', checkedKeys)
setNextSiblings(innerTree) setNextSiblings(innerTree)
setParentNode(innerTree) setParentNode(innerTree)
return innerTree return innerTree

View File

@ -1,4 +1,4 @@
import { TreeData, UseTreeData } from '/@src/module/tree/tree.type' import { TreeData, TreeNode, UseTreeData } from '/@src/module/tree/tree.type'
import { computed, ref, unref, watch } from 'vue' import { computed, ref, unref, watch } from 'vue'
import { import {
getTreeSpreadKeys, getTreeSpreadKeys,
@ -20,15 +20,24 @@ export const useTreeData: UseTreeData = (props, emit) => {
}, },
}) })
const checkedKeys = computed({
get: () => {
return props.checkedKeys!
},
set: (value: (string | number)[]) => {
emit('update:checkedKeys', value)
},
})
/** /**
* data * data
*/ */
const innerTreeData = ref<TreeData[]>([]) const innerTreeData = ref<TreeNode[]>([])
watch( watch(
() => props.data, () => props.data,
(treeData) => { (treeData) => {
if (treeData) { if (treeData) {
innerTreeData.value = initialTreeData(treeData) innerTreeData.value = initialTreeData(treeData, checkedKeys)
} }
}, },
{ immediate: true, deep: true } { immediate: true, deep: true }
@ -60,6 +69,7 @@ export const useTreeData: UseTreeData = (props, emit) => {
return { return {
spreadKeys, spreadKeys,
checkedKeys,
innerTreeData, innerTreeData,
updateInnerTreeData, updateInnerTreeData,
treeWrapperClass, treeWrapperClass,