diff --git a/packages/tree/src/model/node.js b/packages/tree/src/model/node.js index 49461e55a..61b766b9b 100644 --- a/packages/tree/src/model/node.js +++ b/packages/tree/src/model/node.js @@ -22,6 +22,8 @@ export const getChildState = node => { }; const reInitChecked = function(node) { + if (node.childNodes.length === 0) return; + const {all, none, half} = getChildState(node.childNodes); if (all) { node.checked = true; @@ -42,22 +44,6 @@ const reInitChecked = function(node) { } }; -const initLazyLoadChild = node => { - const childNodes = node.childNodes; - if (node.checked) { - for (let i = 0, j = childNodes.length; i < j; i++) { - const child = childNodes[i]; - if (!child.disabled) { - child.checked = true; - } - } - } - - const parent = node.parent; - if (!parent || parent.level === 0) return; - reInitChecked(parent); -}; - const getPropertyFromData = function(node, prop) { const props = node.store.props; const data = node.data || {}; @@ -261,7 +247,11 @@ export default class Node { if (this.shouldLoadData()) { this.loadData((data) => { if (data instanceof Array) { - initLazyLoadChild(this); + if (this.checked) { + this.setChecked(true, true); + } else { + reInitChecked(this); + } done(); } }); @@ -300,45 +290,52 @@ export default class Node { setChecked(value, deep, recursion, passValue) { this.indeterminate = value === 'half'; this.checked = value === true; - let { all, allWithoutDisable } = getChildState(this.childNodes); - if (this.childNodes.length && (!all && allWithoutDisable)) { - this.checked = false; - value = false; - } + if (this.store.checkStrictly) return; - const handleDescendants = (lazy) => { - if (deep && !lazy) { - const childNodes = this.childNodes; - for (let i = 0, j = childNodes.length; i < j; i++) { - const child = childNodes[i]; - passValue = passValue || value !== false; - const isCheck = child.disabled ? child.checked : passValue; - child.setChecked(isCheck, deep, true, passValue); - } - const { half, all } = getChildState(childNodes); - if (!all) { - this.checked = all; - this.indeterminate = half; - } + if (!(this.shouldLoadData() && !this.store.checkDescendants)) { + let { all, allWithoutDisable } = getChildState(this.childNodes); + + if (!this.isLeaf && (!all && allWithoutDisable)) { + this.checked = false; + value = false; } - }; - if (!this.store.checkStrictly && this.shouldLoadData()) { - // Only work on lazy load data. - this.loadData(() => { - handleDescendants(true); - }, { - checked: value !== false - }); - } else { - handleDescendants(); + const handleDescendants = () => { + if (deep) { + const childNodes = this.childNodes; + for (let i = 0, j = childNodes.length; i < j; i++) { + const child = childNodes[i]; + passValue = passValue || value !== false; + const isCheck = child.disabled ? child.checked : passValue; + child.setChecked(isCheck, deep, true, passValue); + } + const { half, all } = getChildState(childNodes); + if (!all) { + this.checked = all; + this.indeterminate = half; + } + } + }; + + if (this.shouldLoadData()) { + // Only work on lazy load data. + this.loadData(() => { + handleDescendants(); + reInitChecked(this); + }, { + checked: value !== false + }); + return; + } else { + handleDescendants(); + } } const parent = this.parent; if (!parent || parent.level === 0) return; - if (!this.store.checkStrictly && !recursion) { + if (!recursion) { reInitChecked(parent); } } diff --git a/packages/tree/src/tree.vue b/packages/tree/src/tree.vue index 2cfab4128..e6fab6d30 100644 --- a/packages/tree/src/tree.vue +++ b/packages/tree/src/tree.vue @@ -53,6 +53,10 @@ type: Boolean, default: true }, + checkDescendants: { + type: Boolean, + default: false + }, autoExpandParent: { type: Boolean, default: true @@ -180,6 +184,7 @@ load: this.load, currentNodeKey: this.currentNodeKey, checkStrictly: this.checkStrictly, + checkDescendants: this.checkDescendants, defaultCheckedKeys: this.defaultCheckedKeys, defaultExpandedKeys: this.defaultExpandedKeys, autoExpandParent: this.autoExpandParent, diff --git a/test/unit/specs/tree.spec.js b/test/unit/specs/tree.spec.js index c0851171f..b7fbcc647 100644 --- a/test/unit/specs/tree.spec.js +++ b/test/unit/specs/tree.spec.js @@ -522,6 +522,100 @@ describe('Tree', () => { }, 100); }); + it('lazy defaultChecked', done => { + vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox', { + methods: { + loadNode(node, resolve) { + if (node.level === 0) { + return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]); + } + if (node.level > 4) return resolve([]); + setTimeout(() => { + resolve([{ + label: 'zone' + this.count, + id: this.count++ + }, { + label: 'zone' + this.count, + id: this.count++ + }]); + }, 50); + } + } + }); + const tree = vm.$children[0]; + const firstNode = document.querySelector('.el-tree-node__content'); + const initStatus = firstNode.querySelector('.is-indeterminate'); + expect(initStatus).to.equal(null); + tree.store.setCheckedKeys([3]); + firstNode.querySelector('.el-tree-node__expand-icon').click(); + setTimeout(() => { + const clickStatus = firstNode.querySelector('.is-indeterminate'); + expect(clickStatus).to.not.equal(null); + const child = document.querySelectorAll('.el-tree-node__content')[1]; + expect(child.querySelector('input').checked).to.equal(true); + done(); + }, 300); + }); + + it('lazy expandOnChecked', done => { + vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox check-descendants', { + methods: { + loadNode(node, resolve) { + if (node.level === 0) { + return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]); + } + if (node.level > 4) return resolve([]); + setTimeout(() => { + resolve([{ + label: 'zone' + this.count, + id: this.count++ + }, { + label: 'zone' + this.count, + id: this.count++ + }]); + }, 50); + } + } + }); + const tree = vm.$children[0]; + tree.store.setCheckedKeys([1]); + setTimeout(() => { + const id5 = document.querySelectorAll('.el-tree-node__content')[3]; + expect(id5.querySelector('input').checked).to.equal(true); + done(); + }, 300); + }); + + it('lazy without expandOnChecked', done => { + vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox', { + methods: { + loadNode(node, resolve) { + if (node.level === 0) { + return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]); + } + if (node.level > 4) return resolve([]); + setTimeout(() => { + resolve([{ + label: 'zone' + this.count, + id: this.count++ + }, { + label: 'zone' + this.count, + id: this.count++ + }]); + }, 50); + } + } + }); + const tree = vm.$children[0]; + tree.store.setCheckedKeys([1]); + setTimeout(() => { + const nodes = document.querySelectorAll('.el-tree-node__content'); + expect(nodes[0].querySelector('input').checked).to.equal(true); + expect(nodes.length).to.equal(2); + done(); + }, 300); + }); + it('accordion', done => { vm = getTreeVm(':props="defaultProps" accordion'); const firstNode = vm.$el.querySelector('.el-tree-node__content');