diff --git a/packages/components/tree/__tests__/tree.test.ts b/packages/components/tree/__tests__/tree.test.ts
index 123d423e63..b3d554ebd5 100644
--- a/packages/components/tree/__tests__/tree.test.ts
+++ b/packages/components/tree/__tests__/tree.test.ts
@@ -1481,6 +1481,102 @@ describe('Tree.vue', () => {
expect(flag).toBe(true)
})
+ test('collapse and navigate down and up', async () => {
+ const { wrapper } = getTreeVm(``, {
+ template: `
+
+
+
+ `,
+ })
+ await nextTick()
+ let flag = false
+ function handleFocus() {
+ return () => (flag = true)
+ }
+ const tree = wrapper.findComponent({ name: 'ElTree' })
+ const targetElement = wrapper.find('div[data-key="2"]').element
+ const fromElement = wrapper.find('div[data-key="1"]')
+ await fromElement.trigger('click')
+
+ expect(fromElement.classes('is-expanded')).toBe(false) // 判断是否已折叠
+
+ await nextTick()
+ defineGetter(targetElement, 'focus', handleFocus)
+ ;(tree.vm as InstanceType).setCurrentKey(1)
+ // 模拟按下下箭头键
+ fromElement.element.dispatchEvent(
+ new KeyboardEvent('keydown', {
+ code: 'ArrowDown',
+ bubbles: true,
+ cancelable: false,
+ })
+ )
+ expect(flag).toBe(true)
+
+ await nextTick()
+
+ flag = false
+ defineGetter(fromElement.element, 'focus', handleFocus)
+ // 模拟按下上箭头键
+ targetElement.dispatchEvent(
+ new KeyboardEvent('keydown', {
+ code: 'ArrowUp',
+ bubbles: true,
+ cancelable: false,
+ })
+ )
+ expect(flag).toBe(true)
+ })
+
+ test('filter-node-method and navigate down', async () => {
+ const { wrapper } = getTreeVm(``, {
+ template: `
+
+
+
+ `,
+ methods: {
+ filterNode(value, data) {
+ if (!value) return true
+ return data.label.includes(value)
+ },
+ },
+ })
+ let flag = false
+ function handleFocus() {
+ return () => (flag = true)
+ }
+
+ const treeWrapper = wrapper.findComponent(Tree)
+ ;(treeWrapper.vm as InstanceType).filter('-1')
+
+ await sleep()
+ const tree = wrapper.findComponent({ name: 'ElTree' })
+ ;(tree.vm as InstanceType).setCurrentKey(1)
+
+ const allNodes = treeWrapper.findAll('.el-tree-node')
+ const visibleNodes = allNodes.filter(
+ (node) => !node.classes().includes('is-hidden')
+ )
+ const len = visibleNodes.length
+ for (let i = 0; i < len; i++) {
+ if (visibleNodes[i + 1]) {
+ defineGetter(visibleNodes[i + 1].element, 'focus', handleFocus)
+ // 模拟按下下箭头键
+ visibleNodes[i].element.dispatchEvent(
+ new KeyboardEvent('keydown', {
+ code: 'ArrowDown',
+ bubbles: true,
+ cancelable: false,
+ })
+ )
+ expect(flag).toBe(true)
+ flag = false
+ }
+ }
+ })
+
test('navigate with disabled', async () => {
const wrapper = mount({
template: `
diff --git a/packages/components/tree/src/model/node.ts b/packages/components/tree/src/model/node.ts
index 24db8976db..9fa84505b3 100644
--- a/packages/components/tree/src/model/node.ts
+++ b/packages/components/tree/src/model/node.ts
@@ -79,6 +79,13 @@ const getPropertyFromData = function (node: Node, prop: string): any {
}
}
+const setCanFocus = function (childNodes: Node[], focus: boolean): void {
+ childNodes.forEach((item) => {
+ item.canFocus = focus
+ setCanFocus(item.childNodes, focus)
+ })
+}
+
let nodeIdSeed = 0
class Node {
@@ -359,9 +366,7 @@ class Node {
}
this.expanded = true
if (callback) callback()
- this.childNodes.forEach((item) => {
- item.canFocus = true
- })
+ setCanFocus(this.childNodes, true)
}
if (this.shouldLoadData()) {
@@ -395,9 +400,7 @@ class Node {
collapse(): void {
this.expanded = false
- this.childNodes.forEach((item) => {
- item.canFocus = false
- })
+ setCanFocus(this.childNodes, false)
}
shouldLoadData() {
diff --git a/packages/components/tree/src/model/useKeydown.ts b/packages/components/tree/src/model/useKeydown.ts
index bbd9be2dc5..ae243de863 100644
--- a/packages/components/tree/src/model/useKeydown.ts
+++ b/packages/components/tree/src/model/useKeydown.ts
@@ -46,8 +46,13 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref) {
: treeItems.length - 1
const startIndex = nextIndex
while (true) {
- if (store.value.getNode(treeItems[nextIndex].dataset.key!).canFocus)
+ const currentNode = store.value.getNode(
+ treeItems[nextIndex].dataset.key!
+ )
+ if (currentNode.canFocus && currentNode.visible) {
break
+ }
+
nextIndex--
if (nextIndex === startIndex) {
nextIndex = -1
@@ -66,8 +71,13 @@ export function useKeydown({ el$ }: UseKeydownOption, store: Ref) {
: 0
const startIndex = nextIndex
while (true) {
- if (store.value.getNode(treeItems[nextIndex].dataset.key!).canFocus)
+ const currentNode = store.value.getNode(
+ treeItems[nextIndex].dataset.key!
+ )
+ if (currentNode.canFocus && currentNode.visible) {
break
+ }
+
nextIndex++
if (nextIndex === startIndex) {
nextIndex = -1