refactor: tree
parent
106b2609be
commit
9cbaeabbd6
|
@ -11,7 +11,7 @@ import {
|
|||
arrDel,
|
||||
posToArr,
|
||||
} from './util';
|
||||
import type { Key, FlattenNode, EventDataNode, NodeInstance, ScrollTo } from './interface';
|
||||
import type { Key, FlattenNode, EventDataNode, ScrollTo, DragNodeEvent } from './interface';
|
||||
import {
|
||||
flattenTreeData,
|
||||
convertTreeToData,
|
||||
|
@ -106,7 +106,7 @@ export default defineComponent({
|
|||
|
||||
let dragStartMousePosition = null;
|
||||
|
||||
let dragNode = null;
|
||||
let dragNode: DragNodeEvent = null;
|
||||
|
||||
const treeNodeRequiredProps = computed(() => {
|
||||
return {
|
||||
|
@ -251,7 +251,7 @@ export default defineComponent({
|
|||
cleanDragState();
|
||||
|
||||
if (onDragend && !outsideTree) {
|
||||
onDragend({ event, node: convertNodePropsToEventData(node.props) });
|
||||
onDragend({ event, node: node.eventData.value });
|
||||
}
|
||||
|
||||
dragNode = null;
|
||||
|
@ -266,7 +266,7 @@ export default defineComponent({
|
|||
|
||||
const onNodeDragStart: NodeDragEventHandler = (event, node) => {
|
||||
const { onDragstart } = props;
|
||||
const { eventKey } = node.props;
|
||||
const { eventKey, eventData } = node;
|
||||
|
||||
dragNode = node;
|
||||
dragStartMousePosition = {
|
||||
|
@ -274,17 +274,17 @@ export default defineComponent({
|
|||
y: event.clientY,
|
||||
};
|
||||
|
||||
const newExpandedKeys = arrDel(expandedKeys.value, eventKey);
|
||||
const newExpandedKeys = arrDel(expandedKeys.value, eventKey.value);
|
||||
|
||||
dragState.dragging = true;
|
||||
dragState.dragChildrenKeys = getDragChildrenKeys(eventKey, keyEntities.value);
|
||||
dragState.dragChildrenKeys = getDragChildrenKeys(eventKey.value, keyEntities.value);
|
||||
indent.value = listRef.value.getIndentWidth();
|
||||
|
||||
setExpandedKeys(newExpandedKeys);
|
||||
window.addEventListener('dragend', onWindowDragEnd);
|
||||
|
||||
if (onDragstart) {
|
||||
onDragstart({ event, node: convertNodePropsToEventData(node.props) });
|
||||
onDragstart({ event, node: eventData.value });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -295,9 +295,8 @@ export default defineComponent({
|
|||
* Better for use mouse move event to refresh drag state.
|
||||
* But let's just keep it to avoid event trigger logic change.
|
||||
*/
|
||||
const onNodeDragEnter = (event: MouseEvent, node: NodeInstance) => {
|
||||
const onNodeDragEnter = (event: MouseEvent, node: DragNodeEvent) => {
|
||||
const { onDragenter, onExpand, allowDrop, direction } = props;
|
||||
const { pos } = node.props;
|
||||
|
||||
const {
|
||||
dropPosition,
|
||||
|
@ -347,27 +346,27 @@ export default defineComponent({
|
|||
clearTimeout(delayedDragEnterLogic[key]);
|
||||
});
|
||||
|
||||
if (dragNode.props.eventKey !== node.props.eventKey) {
|
||||
if (dragNode.eventKey.value !== node.eventKey.value) {
|
||||
// hoist expand logic here
|
||||
// since if logic is on the bottom
|
||||
// it will be blocked by abstract dragover node check
|
||||
// => if you dragenter from top, you mouse will still be consider as in the top node
|
||||
(event as any).persist();
|
||||
delayedDragEnterLogic[pos] = window.setTimeout(() => {
|
||||
delayedDragEnterLogic[node.pos.value] = window.setTimeout(() => {
|
||||
if (!dragState.dragging) return;
|
||||
|
||||
let newExpandedKeys = [...expandedKeys.value];
|
||||
const entity = keyEntities[node.props.eventKey];
|
||||
const entity = keyEntities[node.eventKey.value];
|
||||
|
||||
if (entity && (entity.children || []).length) {
|
||||
newExpandedKeys = arrAdd(expandedKeys.value, node.props.eventKey);
|
||||
newExpandedKeys = arrAdd(expandedKeys.value, node.eventKey.value);
|
||||
}
|
||||
|
||||
setExpandedKeys(newExpandedKeys);
|
||||
|
||||
if (onExpand) {
|
||||
onExpand(newExpandedKeys, {
|
||||
node: convertNodePropsToEventData(node.props),
|
||||
node: node.eventData.value,
|
||||
expanded: true,
|
||||
nativeEvent: (event as any).nativeEvent,
|
||||
});
|
||||
|
@ -376,7 +375,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
// Skip if drag node is self
|
||||
if (dragNode.props.eventKey === dropTargetKey && dropLevelOffset === 0) {
|
||||
if (dragNode.eventKey.value === dropTargetKey && dropLevelOffset === 0) {
|
||||
Object.assign(dragState, {
|
||||
dragOverNodeKey: null,
|
||||
dropPosition: null,
|
||||
|
@ -403,13 +402,13 @@ export default defineComponent({
|
|||
if (onDragenter) {
|
||||
onDragenter({
|
||||
event,
|
||||
node: convertNodePropsToEventData(node.props),
|
||||
node: node.eventData.value,
|
||||
expandedKeys: expandedKeys.value,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onNodeDragOver = (event: MouseEvent, node: NodeInstance) => {
|
||||
const onNodeDragOver = (event: MouseEvent, node: DragNodeEvent) => {
|
||||
const { onDragover, allowDrop, direction } = props;
|
||||
|
||||
const {
|
||||
|
@ -441,7 +440,7 @@ export default defineComponent({
|
|||
|
||||
// Update drag position
|
||||
|
||||
if (dragNode.props.eventKey === dropTargetKey && dropLevelOffset === 0) {
|
||||
if (dragNode.eventKey.value === dropTargetKey && dropLevelOffset === 0) {
|
||||
if (
|
||||
!(
|
||||
dragState.dropPosition === null &&
|
||||
|
@ -486,7 +485,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
if (onDragover) {
|
||||
onDragover({ event, node: convertNodePropsToEventData(node.props) });
|
||||
onDragover({ event, node: node.eventData.value });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -494,7 +493,7 @@ export default defineComponent({
|
|||
const { onDragleave } = props;
|
||||
|
||||
if (onDragleave) {
|
||||
onDragleave({ event, node: convertNodePropsToEventData(node.props) });
|
||||
onDragleave({ event, node: node.eventData.value });
|
||||
}
|
||||
};
|
||||
const onNodeDrop = (event: MouseEvent, _node, outsideTree = false) => {
|
||||
|
@ -527,8 +526,8 @@ export default defineComponent({
|
|||
const dropResult = {
|
||||
event,
|
||||
node: convertNodePropsToEventData(abstractDropNodeProps),
|
||||
dragNode: dragNode ? convertNodePropsToEventData(dragNode.props) : null,
|
||||
dragNodesKeys: [dragNode.props.eventKey].concat(dragChildrenKeys),
|
||||
dragNode: dragNode ? dragNode.eventData.value : null,
|
||||
dragNodesKeys: [dragNode.eventKey.value].concat(dragChildrenKeys),
|
||||
dropToGap: dropPosition !== 0,
|
||||
dropPosition: dropPosition + Number(posArr[posArr.length - 1]),
|
||||
};
|
||||
|
@ -804,9 +803,10 @@ export default defineComponent({
|
|||
// );
|
||||
// flattenNodes.value = newFlattenTreeData;
|
||||
})
|
||||
.catch(() => {
|
||||
.catch(e => {
|
||||
const expandedKeysToRestore = arrDel(expandedKeys.value, key);
|
||||
setExpandedKeys(expandedKeysToRestore);
|
||||
Promise.reject(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -874,7 +874,13 @@ export default defineComponent({
|
|||
onActiveChange(null);
|
||||
}
|
||||
};
|
||||
|
||||
const activeItemEventNode = computed(() => {
|
||||
return convertNodePropsToEventData({
|
||||
...getTreeNodeProps(activeKey.value, treeNodeRequiredProps.value),
|
||||
data: activeItem.value.data,
|
||||
active: true,
|
||||
});
|
||||
});
|
||||
const onKeyDown = event => {
|
||||
const { onKeyDown, checkable, selectable } = props;
|
||||
|
||||
|
@ -896,11 +902,7 @@ export default defineComponent({
|
|||
const item = activeItem.value;
|
||||
if (item && item.data) {
|
||||
const expandable = item.data.isLeaf === false || !!(item.data.children || []).length;
|
||||
const eventNode = convertNodePropsToEventData({
|
||||
...getTreeNodeProps(activeKey.value, treeNodeRequiredProps.value),
|
||||
data: item.data,
|
||||
active: true,
|
||||
});
|
||||
const eventNode = activeItemEventNode.value;
|
||||
|
||||
switch (event.which) {
|
||||
// >>> Expand
|
||||
|
|
|
@ -6,6 +6,7 @@ import { computed, defineComponent, getCurrentInstance, onMounted, onUpdated, re
|
|||
import { treeNodeProps } from './props';
|
||||
import classNames from '../_util/classNames';
|
||||
import { warning } from '../vc-util/warning';
|
||||
import { DragNodeEvent } from './interface';
|
||||
|
||||
const ICON_OPEN = 'open';
|
||||
const ICON_CLOSE = 'close';
|
||||
|
@ -18,14 +19,13 @@ export default defineComponent({
|
|||
props: treeNodeProps,
|
||||
isTreeNode: 1,
|
||||
slots: ['title', 'icon', 'switcherIcon', 'checkable'],
|
||||
setup(props, { attrs, slots }) {
|
||||
setup(props, { attrs, slots, expose }) {
|
||||
warning(
|
||||
!('slots' in props.data),
|
||||
'treeData slots is deprecated, please use `v-slot:icon` or `v-slot:title`, `v-slot:switcherIcon` instead',
|
||||
);
|
||||
const dragNodeHighlight = ref(false);
|
||||
const context = useInjectTreeContext();
|
||||
const instance = getCurrentInstance();
|
||||
const selectHandle = ref();
|
||||
|
||||
const hasChildren = computed(() => {
|
||||
|
@ -86,9 +86,19 @@ export default defineComponent({
|
|||
return treeSelectable;
|
||||
});
|
||||
|
||||
const eventData = computed(() => {
|
||||
return convertNodePropsToEventData(props);
|
||||
});
|
||||
const dragNodeEvent: DragNodeEvent = {
|
||||
eventData,
|
||||
eventKey: computed(() => props.eventKey),
|
||||
selectHandle,
|
||||
pos: computed(() => props.pos),
|
||||
};
|
||||
expose(dragNodeEvent);
|
||||
const onSelectorDoubleClick = (e: MouseEvent) => {
|
||||
const { onNodeDoubleClick } = context.value;
|
||||
onNodeDoubleClick(e, convertNodePropsToEventData(props));
|
||||
onNodeDoubleClick(e, eventData.value);
|
||||
};
|
||||
|
||||
const onSelect = (e: MouseEvent) => {
|
||||
|
@ -96,7 +106,7 @@ export default defineComponent({
|
|||
|
||||
const { onNodeSelect } = context.value;
|
||||
e.preventDefault();
|
||||
onNodeSelect(e, convertNodePropsToEventData(props));
|
||||
onNodeSelect(e, eventData.value);
|
||||
};
|
||||
|
||||
const onCheck = (e: MouseEvent) => {
|
||||
|
@ -109,13 +119,13 @@ export default defineComponent({
|
|||
|
||||
e.preventDefault();
|
||||
const targetChecked = !checked;
|
||||
onNodeCheck(e, convertNodePropsToEventData(props), targetChecked);
|
||||
onNodeCheck(e, eventData.value, targetChecked);
|
||||
};
|
||||
|
||||
const onSelectorClick = (e: MouseEvent) => {
|
||||
// Click trigger before select/check operation
|
||||
const { onNodeClick } = context.value;
|
||||
onNodeClick(e, convertNodePropsToEventData(props));
|
||||
onNodeClick(e, eventData.value);
|
||||
|
||||
if (isSelectable.value) {
|
||||
onSelect(e);
|
||||
|
@ -126,17 +136,17 @@ export default defineComponent({
|
|||
|
||||
const onMouseEnter = (e: MouseEvent) => {
|
||||
const { onNodeMouseEnter } = context.value;
|
||||
onNodeMouseEnter(e, convertNodePropsToEventData(props));
|
||||
onNodeMouseEnter(e, eventData.value);
|
||||
};
|
||||
|
||||
const onMouseLeave = (e: MouseEvent) => {
|
||||
const { onNodeMouseLeave } = context.value;
|
||||
onNodeMouseLeave(e, convertNodePropsToEventData(props));
|
||||
onNodeMouseLeave(e, eventData.value);
|
||||
};
|
||||
|
||||
const onContextmenu = (e: MouseEvent) => {
|
||||
const { onNodeContextMenu } = context.value;
|
||||
onNodeContextMenu(e, convertNodePropsToEventData(props));
|
||||
onNodeContextMenu(e, eventData.value);
|
||||
};
|
||||
|
||||
const onDragStart = (e: DragEvent) => {
|
||||
|
@ -144,7 +154,7 @@ export default defineComponent({
|
|||
|
||||
e.stopPropagation();
|
||||
dragNodeHighlight.value = true;
|
||||
onNodeDragStart(e, instance.vnode);
|
||||
onNodeDragStart(e, dragNodeEvent);
|
||||
|
||||
try {
|
||||
// ie throw error
|
||||
|
@ -160,7 +170,7 @@ export default defineComponent({
|
|||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onNodeDragEnter(e, instance.vnode);
|
||||
onNodeDragEnter(e, dragNodeEvent);
|
||||
};
|
||||
|
||||
const onDragOver = (e: DragEvent) => {
|
||||
|
@ -168,14 +178,14 @@ export default defineComponent({
|
|||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onNodeDragOver(e, instance.vnode);
|
||||
onNodeDragOver(e, dragNodeEvent);
|
||||
};
|
||||
|
||||
const onDragLeave = (e: DragEvent) => {
|
||||
const { onNodeDragLeave } = context.value;
|
||||
|
||||
e.stopPropagation();
|
||||
onNodeDragLeave(e, instance.vnode);
|
||||
onNodeDragLeave(e, dragNodeEvent);
|
||||
};
|
||||
|
||||
const onDragEnd = (e: DragEvent) => {
|
||||
|
@ -183,7 +193,7 @@ export default defineComponent({
|
|||
|
||||
e.stopPropagation();
|
||||
dragNodeHighlight.value = false;
|
||||
onNodeDragEnd(e, instance.vnode);
|
||||
onNodeDragEnd(e, dragNodeEvent);
|
||||
};
|
||||
|
||||
const onDrop = (e: DragEvent) => {
|
||||
|
@ -192,14 +202,14 @@ export default defineComponent({
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragNodeHighlight.value = false;
|
||||
onNodeDrop(e, instance.vnode);
|
||||
onNodeDrop(e, dragNodeEvent);
|
||||
};
|
||||
|
||||
// Disabled item still can be switch
|
||||
const onExpand = e => {
|
||||
const { onNodeExpand } = context.value;
|
||||
if (props.loading) return;
|
||||
onNodeExpand(e, convertNodePropsToEventData(props));
|
||||
onNodeExpand(e, eventData.value);
|
||||
};
|
||||
|
||||
const renderSwitcherIconDom = (isLeaf: boolean) => {
|
||||
|
@ -231,7 +241,7 @@ export default defineComponent({
|
|||
// We needn't reload data when has children in sync logic
|
||||
// It's only needed in node expanded
|
||||
if (!hasChildren.value && !loaded) {
|
||||
onNodeLoad(convertNodePropsToEventData(props));
|
||||
onNodeLoad(eventData.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -240,7 +250,7 @@ export default defineComponent({
|
|||
syncLoadData();
|
||||
});
|
||||
onUpdated(() => {
|
||||
syncLoadData();
|
||||
//syncLoadData();
|
||||
});
|
||||
|
||||
// Switcher
|
||||
|
@ -454,7 +464,7 @@ export default defineComponent({
|
|||
'drag-over': !disabled && dragOver,
|
||||
'drag-over-gap-top': !disabled && dragOverGapTop,
|
||||
'drag-over-gap-bottom': !disabled && dragOverGapBottom,
|
||||
'filter-node': filterTreeNode && filterTreeNode(convertNodePropsToEventData(props)),
|
||||
'filter-node': filterTreeNode && filterTreeNode(eventData.value),
|
||||
})}
|
||||
style={attrs.style}
|
||||
onDragenter={mergedDraggable ? onDragEnter : undefined}
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
Key,
|
||||
DataEntity,
|
||||
EventDataNode,
|
||||
NodeInstance,
|
||||
DragNodeEvent,
|
||||
DataNode,
|
||||
Direction,
|
||||
} from './interface';
|
||||
|
@ -30,7 +30,7 @@ export type NodeDragEventParams = {
|
|||
export type NodeMouseEventHandler = (e: MouseEvent, node: EventDataNode) => void;
|
||||
export type NodeDragEventHandler = (
|
||||
e: MouseEvent,
|
||||
node: NodeInstance,
|
||||
node: DragNodeEvent,
|
||||
outsideTree?: boolean,
|
||||
) => void;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { CSSProperties, VNode } from 'vue';
|
||||
import type { ComputedRef, CSSProperties, Ref, VNode } from 'vue';
|
||||
export type { ScrollTo } from '../vc-virtual-list/List';
|
||||
|
||||
export interface DataNode {
|
||||
|
@ -31,6 +31,8 @@ export interface EventDataNode extends DataNode {
|
|||
dragOverGapBottom: boolean;
|
||||
pos: string;
|
||||
active: boolean;
|
||||
dataRef: DataNode;
|
||||
eventKey: Key; // 兼容 v2, 推荐直接用 key
|
||||
}
|
||||
|
||||
export type IconType = any;
|
||||
|
@ -38,16 +40,17 @@ export type IconType = any;
|
|||
export type Key = string | number;
|
||||
|
||||
export type NodeElement = VNode & {
|
||||
selectHandle?: HTMLSpanElement;
|
||||
type: {
|
||||
isTreeNode: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type NodeInstance = VNode & {
|
||||
selectHandle?: HTMLSpanElement;
|
||||
export type DragNodeEvent = {
|
||||
eventData: ComputedRef<EventDataNode>;
|
||||
eventKey: ComputedRef<Key>;
|
||||
selectHandle: Ref<HTMLSpanElement>;
|
||||
pos: ComputedRef<string>;
|
||||
};
|
||||
|
||||
export interface Entity {
|
||||
node: NodeElement;
|
||||
index: number;
|
||||
|
|
|
@ -9,9 +9,9 @@ import type {
|
|||
Key,
|
||||
DataNode,
|
||||
DataEntity,
|
||||
NodeInstance,
|
||||
FlattenNode,
|
||||
Direction,
|
||||
DragNodeEvent,
|
||||
} from './interface';
|
||||
import { warning } from '../vc-util/warning';
|
||||
import type { AllowDrop, TreeNodeProps, TreeProps } from './props';
|
||||
|
@ -79,8 +79,8 @@ export function isFirstChild(treeNodeEntity: DataEntity) {
|
|||
// Only used when drag, not affect SSR.
|
||||
export function calcDropPosition(
|
||||
event: MouseEvent,
|
||||
_dragNode: NodeInstance,
|
||||
targetNode: NodeInstance,
|
||||
_dragNode: DragNodeEvent,
|
||||
targetNode: DragNodeEvent,
|
||||
indent: number,
|
||||
startMousePosition: {
|
||||
x: number;
|
||||
|
@ -108,7 +108,7 @@ export function calcDropPosition(
|
|||
const rawDropLevelOffset = (horizontalMouseOffset - 12) / indent;
|
||||
|
||||
// find abstract drop node by horizontal offset
|
||||
let abstractDropNodeEntity: DataEntity = keyEntities[targetNode.props.eventKey];
|
||||
let abstractDropNodeEntity: DataEntity = keyEntities[targetNode.eventKey.value];
|
||||
|
||||
if (clientY < top + height / 2) {
|
||||
// first half, set abstract drop node to previous node
|
||||
|
@ -150,7 +150,7 @@ export function calcDropPosition(
|
|||
dropNode: abstractDropDataNode,
|
||||
dropPosition: -1,
|
||||
}) &&
|
||||
abstractDropNodeEntity.key === targetNode.props.eventKey
|
||||
abstractDropNodeEntity.key === targetNode.eventKey.value
|
||||
) {
|
||||
// first half of first node in first level
|
||||
dropPosition = -1;
|
||||
|
|
|
@ -393,8 +393,9 @@ export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode
|
|||
dragOverGapBottom,
|
||||
pos,
|
||||
active,
|
||||
dataRef: data,
|
||||
eventKey: data.key,
|
||||
};
|
||||
|
||||
if (!('props' in eventData)) {
|
||||
Object.defineProperty(eventData, 'props', {
|
||||
get() {
|
||||
|
|
Loading…
Reference in New Issue