vue-tree-kl
Version:
A vue tree component using virtual list.
112 lines (94 loc) • 3.65 kB
text/typescript
import { Ref, nextTick, ref } from "vue"
import { TreeNode } from "../store"
import { TreeProps } from "../components/Tree.vue"
type IUseExpandAnimationProps = Required<Pick<TreeProps,
'keyField' |
'animation'
>>
export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, renderStartRef: Ref<number>, props: IUseExpandAnimationProps) => {
const expandAnimationStart = ref(false)
const expandAnimationReady = ref(false)
const expandNodeIndex = ref(-1)
const expandNodeLevel = ref(-1)
const expandNodeCurrentState = ref(false)
const expandNodeNextState = ref(false)
const expandRenderStart = ref(0)
const expandTopNodes = ref<TreeNode[]>([])
const expandMiddleNodes = ref<TreeNode[]>([])
const expandBottomNodes = ref<TreeNode[]>([])
const resetExpandAnimation = () => {
expandAnimationStart.value = false
expandAnimationReady.value = false
expandNodeIndex.value = -1
expandNodeLevel.value = -1
expandRenderStart.value = 0
expandTopNodes.value = []
expandMiddleNodes.value = []
expandBottomNodes.value = []
}
const updateMiddleNodes = () => {
const nodeToExpandLevel = expandNodeLevel.value
const middleNodes: TreeNode[] = []
const renderNodesLength = renderNodesRef.value.length
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
for (let i = expandNodeIndex.value - expandRenderStartDiff + 1; i < renderNodesLength; i++) {
if (renderNodesRef.value[i]._level > nodeToExpandLevel) {
middleNodes.push(renderNodesRef.value[i])
} else break
}
expandMiddleNodes.value = middleNodes
}
const updateBeforeExpand = (nodeToExpand: TreeNode) => {
if (!props.animation) return
resetExpandAnimation()
const key = nodeToExpand[props.keyField]
const index = renderNodesRef.value.findIndex((renderNode) => renderNode[props.keyField] === key)
if (index > -1) {
expandNodeIndex.value = index
expandNodeLevel.value = nodeToExpand._level
expandAnimationStart.value = true
expandNodeCurrentState.value = nodeToExpand.expand
expandNodeNextState.value = !nodeToExpand.expand
expandRenderStart.value = renderStartRef.value
if (expandNodeNextState.value) {
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value + 1)
} else {
updateMiddleNodes()
}
}
}
const updateAfterExpand = () => {
if (!props.animation) return
if (!expandAnimationStart.value) {
expandAnimationStart.value = false
return
}
if (expandNodeIndex.value === -1) return
nextTick(() => {
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
expandTopNodes.value = renderNodesRef.value.slice(0, expandNodeIndex.value - expandRenderStartDiff + 1)
if (expandNodeNextState.value) {
updateMiddleNodes()
} else {
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value - expandRenderStartDiff + 1)
}
expandAnimationReady.value = true
nextTick(() => {
expandNodeCurrentState.value = !expandNodeCurrentState.value
})
})
}
const onExpandAnimationFinish = () => {
resetExpandAnimation()
}
return {
ready: expandAnimationReady,
currentExpandState: expandNodeCurrentState,
topNodes: expandTopNodes,
middleNodes: expandMiddleNodes,
bottomNodes: expandBottomNodes,
updateBeforeExpand,
updateAfterExpand,
onExpandAnimationFinish,
}
}