kingdot
Version:
A UI Components Library For Vue
122 lines (110 loc) • 3.68 kB
JavaScript
import { arrayEquals } from '../../src/utils/utils.js';
let uid = 0;
export default class Node {
constructor(data, config, parent) {
this.data = data;
// 配置
this.config = config;
this.parent = parent || null;
this.uid = uid++;
this.level = this.parent ? this.parent.level + 1 : 1;
const { labelName, valueName } = this.config;
this.value = this.data[valueName];
this.label = this.data[labelName];
// 路径
this.pathNodes = this.calculatePathNodes();
this.pathValue = this.pathNodes.map(node => node.value);
this.pathLabels = this.pathNodes.map(node => node.label);
this.labelText = this.pathLabels.join(' / ');
// lazy
this.loading = false;
this.loaded = false;
// 初始化子元素
const childrenData = this.data.children;
this.children = (childrenData || []).map(child => new Node(child, config, this));
}
calculatePathNodes() {
const nodes = [this];
let parent = this.parent;
while (parent) {
nodes.unshift(parent);
parent = parent.parent;
}
return nodes;
}
get isLeaf() {
const { loaded, children, data } = this;
const { lazy } = this.config;
const len = children.length;
if (lazy) {
if (data.leaf !== undefined && data.leaf !== null) {
return data.leaf;
}
return loaded ? !len : false;
}
return !len;
}
get isDisabled() {
const { data, parent } = this;
return data.disabled || (parent && parent.isDisabled);
}
// 多选
multiCheck(checked) {
if (this.checked !== checked) {
if (this.config.checkStrictly) {
this.checked = checked;
} else {
// 先处理children
this.broadcast('check', checked);
this.setCheckState(checked);
// 处理parent
this.emit('check');
}
}
}
broadcast(event, checked) {
this.children && this.children.forEach(child => {
if (child) {
child.broadcast(event, checked);
if (!child.isDisabled) {
child.setCheckState(checked);
}
}
});
}
emit(event) {
const { parent } = this;
if (parent) {
parent.childCheck && parent.childCheck();
parent.emit(event);
}
}
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.indeterminate = checkedNum !== totalNum && checkedNum > 0;
this.checked = checked;
}
childCheck() {
const { children } = this;
const validChildren = children.filter(child => !child.isDisabled);
const checked = validChildren.length
? validChildren.every(child => child.checked)
: false;
this.setCheckState(checked);
}
// 更新选中状态
syncCheckState(checkedValue) {
const checked = this.isContainNode(checkedValue, this.pathValue);
this.multiCheck(checked);
}
isContainNode(checkedValue) {
const value = this.pathValue;
return this.config.multiple && checkedValue.length
? checkedValue.some(val => arrayEquals(val, value))
: arrayEquals(checkedValue, value);
}
}