| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- import { isEqual, capitalize } from 'element-ui/src/utils/util';
- import { isDef } from 'element-ui/src/utils/shared';
- let uid = 0;
- export default class Node {
- constructor(data, config, parentNode) {
- this.data = data;
- this.config = config;
- this.parent = parentNode || null;
- this.level = !this.parent ? 1 : this.parent.level + 1;
- this.uid = uid++;
- this.initState();
- this.initChildren();
- }
- initState() {
- const { value: valueKey, label: labelKey } = this.config;
- this.value = this.data[valueKey];
- this.label = this.data[labelKey];
- this.pathNodes = this.calculatePathNodes();
- this.path = this.pathNodes.map(node => node.value);
- this.pathLabels = this.pathNodes.map(node => node.label);
- // lazy load
- this.loading = false;
- this.loaded = false;
- }
- initChildren() {
- const { config } = this;
- const childrenKey = config.children;
- const childrenData = this.data[childrenKey];
- this.hasChildren = Array.isArray(childrenData);
- this.children = (childrenData || []).map(child => new Node(child, config, this));
- }
- get isDisabled() {
- const { data, parent, config } = this;
- const disabledKey = config.disabled;
- const { checkStrictly } = config;
- return data[disabledKey] ||
- !checkStrictly && parent && parent.isDisabled;
- }
- get isLeaf() {
- const { data, loaded, hasChildren, children } = this;
- const { lazy, leaf: leafKey } = this.config;
- if (lazy) {
- const isLeaf = isDef(data[leafKey])
- ? data[leafKey]
- : (loaded ? !children.length : false);
- this.hasChildren = !isLeaf;
- return isLeaf;
- }
- return !hasChildren;
- }
- calculatePathNodes() {
- const nodes = [this];
- let parent = this.parent;
- while (parent) {
- nodes.unshift(parent);
- parent = parent.parent;
- }
- return nodes;
- }
- getPath() {
- return this.path;
- }
- getValue() {
- return this.value;
- }
- getValueByOption() {
- return this.config.emitPath
- ? this.getPath()
- : this.getValue();
- }
- getText(allLevels, separator) {
- return allLevels ? this.pathLabels.join(separator) : this.label;
- }
- isSameNode(checkedValue) {
- const value = this.getValueByOption();
- return this.config.multiple && Array.isArray(checkedValue)
- ? checkedValue.some(val => isEqual(val, value))
- : isEqual(checkedValue, value);
- }
- broadcast(event, ...args) {
- const handlerName = `onParent${capitalize(event)}`;
- this.children.forEach(child => {
- if (child) {
- // bottom up
- child.broadcast(event, ...args);
- child[handlerName] && child[handlerName](...args);
- }
- });
- }
- emit(event, ...args) {
- const { parent } = this;
- const handlerName = `onChild${capitalize(event)}`;
- if (parent) {
- parent[handlerName] && parent[handlerName](...args);
- parent.emit(event, ...args);
- }
- }
- onParentCheck(checked) {
- if (!this.isDisabled) {
- this.setCheckState(checked);
- }
- }
- onChildCheck() {
- const { children } = this;
- const validChildren = children.filter(child => !child.isDisabled);
- const checked = validChildren.length
- ? validChildren.every(child => child.checked)
- : false;
- this.setCheckState(checked);
- }
- setCheckState(checked) {
- const totalNum = this.children.length;
- const checkedNum = this.children.reduce((c, p) => {
- const num = p.checked ? 1 : (p.indeterminate ? 0.5 : 0);
- return c + num;
- }, 0);
- this.checked = checked;
- this.indeterminate = checkedNum !== totalNum && checkedNum > 0;
- }
- syncCheckState(checkedValue) {
- const value = this.getValueByOption();
- const checked = this.isSameNode(checkedValue, value);
- this.doCheck(checked);
- }
- doCheck(checked) {
- if (this.checked !== checked) {
- if (this.config.checkStrictly) {
- this.checked = checked;
- } else {
- // bottom up to unify the calculation of the indeterminate state
- this.broadcast('check', checked);
- this.setCheckState(checked);
- this.emit('check');
- }
- }
- }
- }
|