feat(tree): support accrodion animation

This commit is contained in:
07akioni 2022-07-05 00:39:22 +08:00
parent acfdca7cde
commit 50adfe99a2
3 changed files with 31 additions and 21 deletions

View File

@ -29,7 +29,7 @@ checkbox-placement.vue
| Name | Type | default | Description | Version |
| --- | --- | --- | --- | --- |
| accordion | `boolean` | `false` | Whether to use accrodion expand mode. Please note that it will make expand animation not working in some circumstances. We may fix it later, but if you want to use the prop, you should know it. | NEXT_VERSION |
| accordion | `boolean` | `false` | Whether to use accrodion expand mode. | NEXT_VERSION |
| allow-checking-not-loaded | `boolean` | `false` | Whether to allow cascade checking on not loaded nodes. If you want to use this, you should know the `check-keys` may be incomplete. Also, you should aware about the consistency bewteen naive's checking logic and your backend's checking logic, especially when there are disabled nodes. | 2.28.1 |
| allow-drop | `(info: { dropPosition: DropPosition, node: TreeOption, phase: 'drag' \| 'drop' }) => boolean` | A function that prohibit dropping inside leaf node. | Whether to allow dropping. | |
| block-line | `boolean` | `false` | Nodes spread out the whole row. | |
@ -41,7 +41,7 @@ checkbox-placement.vue
| checkbox-placement | `'left' \| 'right'` | `'left'` | Checkbox's placement. | 2.28.3 |
| children-field | `string` | `'children'` | The children field in `TreeOption`. | |
| checked-keys | `Array<string \| number>` | `undefined` | Checked keys of the tree. | |
| check-on-click | `boolean \| ((node: TreeOption) => boolean)` | `true` | Allow node clicking to trigger check when `checkable` is `true` | NEXT_VERSION |
| check-on-click | `boolean \| ((node: TreeOption) => boolean)` | `false` | Allow node clicking to trigger check when `checkable` is `true` | NEXT_VERSION |
| data | `Array<TreeOption>` | `[]` | The node data of the tree. Reset `data` will cause clearing of some uncontrolled status. If you need to modify data, you'd better make tree work in a controlled manner. | |
| default-checked-keys | `Array<string \| number>` | `[]` | Multiple options selected by default. | |
| default-expand-all | `boolean` | `false` | Expand all options. | |

View File

@ -33,7 +33,7 @@ scroll-debug.vue
| 名称 | 类型 | 默认值 | 说明 | 版本 |
| --- | --- | --- | --- | --- |
| accordion | `boolean` | `false` | 是否使用手风琴展开模式。需要注意的是这个属性会导致某些情况下展开动画的丢失,我们未来可能会修复这个问题,但是如果你要使用这个属性,请了解这一点 | NEXT_VERSION |
| accordion | `boolean` | `false` | 是否使用手风琴展开模式 | NEXT_VERSION |
| allow-checking-not-loaded | `boolean` | `false` | 是否允许级联勾选还没有完全加载的节点。如果你要用这个属性,请记住 `checked-keys` 可能是不完整的,并且请注意勾选行为和后端计算逻辑的一致性,尤其是有禁用节点的情况下 | 2.28.1 |
| allow-drop | `(info: { dropPosition: DropPosition, node: TreeOption, phase: 'drag' \| 'drop' }) => boolean` | 一个不允许 drop 在叶节点内部的函数 | 是否允许 drop | |
| block-line | `boolean` | `false` | 节点整行撑开 | |
@ -45,7 +45,7 @@ scroll-debug.vue
| checkbox-placement | `'left' \| 'right'` | `'left'` | 复选框的位置 | 2.28.3 |
| children-field | `string` | `'children'` | 替代 `TreeOption` 中的 children 字段名 | |
| checked-keys | `Array<string \| number>` | `undefined` | 如果设定则 `checked` 状态受控 | |
| check-on-click | `boolean \| ((node: TreeOption) => boolean)` | `true` | 是否允许点击节点进行勾选,仅在 `checkable``true` 时生效 | NEXT_VERSION |
| check-on-click | `boolean \| ((node: TreeOption) => boolean)` | `false` | 是否允许点击节点进行勾选,仅在 `checkable``true` 时生效 | NEXT_VERSION |
| data | `Array<TreeOption>` | `[]` | 树的节点数据。重新设置 `data` 会将一些非受控状态清空,如果你需要在使用中改动 `data`,最好以受控的方式控制树 | |
| default-checked-keys | `Array<string \| number>` | `[]` | 默认选中的多选项 | |
| default-expand-all | `boolean` | `false` | 展开全部选项 | |

View File

@ -146,7 +146,7 @@ export const treeProps = {
expandOnClick: Boolean,
checkOnClick: {
type: [Boolean, Function] as PropType<boolean | CheckOnClick>,
default: true
default: false
},
cancelable: {
type: Boolean,
@ -557,7 +557,7 @@ export default defineComponent({
// animation in progress
const aipRef = ref(false)
// animation flattened nodes
const afNodeRef = ref<Array<TmNode | MotionData>>([])
const afNodesRef = ref<Array<TmNode | MotionData>>([])
// Note: Since the virtual list depends on min height, if there's a node
// whose height starts from 0, the virtual list will have a wrong height
// during animation. This will seldom cause wired scrollbar status. It is
@ -584,10 +584,7 @@ export default defineComponent({
removedKey = expandedKey
}
}
if (
(addedKey !== null && removedKey !== null) ||
(addedKey === null && removedKey === null)
) {
if (addedKey === null && removedKey === null) {
// 1. multi action, not triggered by click
// 2. no action, don't know what happened
return
@ -597,20 +594,34 @@ export default defineComponent({
virtualScroll ? virtualListInstRef.value!.listElRef : selfElRef.value!
).offsetHeight
const viewportItemCount = Math.ceil(viewportHeight / ITEM_SIZE) + 1
// play add animation
let baseExpandedKeys: Key[] | undefined
if (addedKey !== null) {
// play add animation
aipRef.value = true
afNodeRef.value = displayTreeMateRef.value.getFlattenedNodes(prevValue)
const expandedNodeIndex = afNodeRef.value.findIndex(
baseExpandedKeys = prevValue
}
if (removedKey !== null) {
if (baseExpandedKeys === undefined) {
baseExpandedKeys = value
} else {
baseExpandedKeys = baseExpandedKeys.filter(
(key) => key !== removedKey
)
}
}
aipRef.value = true
afNodesRef.value =
displayTreeMateRef.value.getFlattenedNodes(baseExpandedKeys)
if (addedKey !== null) {
const expandedNodeIndex = afNodesRef.value.findIndex(
(node) => (node as any).key === addedKey
)
if (~expandedNodeIndex) {
const expandedChildren = flatten(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(afNodeRef.value[expandedNodeIndex] as TmNode).children!,
(afNodesRef.value[expandedNodeIndex] as TmNode).children!,
value
)
afNodeRef.value.splice(expandedNodeIndex + 1, 0, {
afNodesRef.value.splice(expandedNodeIndex + 1, 0, {
__motion: true,
mode: 'expand',
height: virtualScroll
@ -623,13 +634,12 @@ export default defineComponent({
}
}
if (removedKey !== null) {
afNodeRef.value = displayTreeMateRef.value.getFlattenedNodes(value)
const collapsedNodeIndex = afNodeRef.value.findIndex(
const collapsedNodeIndex = afNodesRef.value.findIndex(
(node) => (node as any).key === removedKey
)
if (~collapsedNodeIndex) {
const collapsedNodeChildren = (
afNodeRef.value[collapsedNodeIndex] as TmNode
afNodesRef.value[collapsedNodeIndex] as TmNode
).children
// Sometime the whole tree is change, remove a key doesn't mean it is collapsed,
// but maybe children removed
@ -637,7 +647,7 @@ export default defineComponent({
// play remove animation
aipRef.value = true
const collapsedChildren = flatten(collapsedNodeChildren, value)
afNodeRef.value.splice(collapsedNodeIndex + 1, 0, {
afNodesRef.value.splice(collapsedNodeIndex + 1, 0, {
__motion: true,
mode: 'collapse',
height: virtualScroll
@ -656,7 +666,7 @@ export default defineComponent({
})
const mergedFNodesRef = computed(() => {
if (aipRef.value) return afNodeRef.value
if (aipRef.value) return afNodesRef.value
else return fNodesRef.value
})