big-ee-ui
Version:
基于element-ui二次封装的UI库
254 lines (218 loc) • 7.02 kB
JavaScript
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.inActivePath = false
this.checked = false
this.refreshFlag = false
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
}
initFirstLevelNodes(nodes) {
this.firstLevelNodes = nodes
}
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)
}
set isDisabled(flag) {
const { data, config } = this
const disabledKey = config.disabled
data[disabledKey] = flag
}
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
}
getPathLabels() {
return this.pathLabels
}
getLabel() {
return this.label
}
getValueByOption() {
return this.config.emitPath ? this.getPath() : this.getValue()
}
// 获取label集合
getLabelByOption() {
return this.config.emitPath ? this.getPathLabels() : this.getLabel()
}
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) {
let { config, level, children } = this
const handlerName = `onParent${capitalize(event)}`
//
//
if (config.mutualExcluseLabel && level + 1 === config.mutualExcluseLabel && args[0]) {
if (children[0]) {
let child = children[0]
child.broadcast(event, ...args)
child[handlerName] && child[handlerName](...args)
}
} else {
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) {
let { config, level } = this
const totalNum = this.children.length
let disabledCounter = 0
let indeterminateCounter = 0
const checkedNum = this.children.reduce((c, p) => {
p.isDisabled && disabledCounter++
p.indeterminate && indeterminateCounter++
const num = p.checked ? 1 : p.indeterminate ? 0.5 : 0
return c + num
}, 0)
this.checked = checked
this.indeterminate = checkedNum !== totalNum && checkedNum > 0
// checkedindeterminate
//
if (config.mutualExcluseLabel && this.children.length > 0) {
// + 1 >=
// checkedinterminate
if (config.mutualExcluseLabel >= level + 1) {
if (disabledCounter + checkedNum === this.children.length) {
this.checked = true
this.indeterminate = false
} else {
// indeterminate
this.checked = false
this.indeterminate = checkedNum > 0 || indeterminateCounter > 0
}
// checked
this.refreshFlag = !this.refreshFlag
}
}
this.mutualExclusion()
}
syncCheckState(checkedValue) {
const value = this.getValueByOption()
const checked = this.isSameNode(checkedValue, value)
// this.doCheck(checked);
this.doCheck(checked, false, true)
}
// checked
mutualExclusion() {
//
const { checked, indeterminate, level, value, parent, config } = this
if (!checked && !indeterminate) return
if (config.mutualExcluseLabel && config.mutualExcluseLabel === level) {
if (level === 1) {
this.firstLevelNodes.forEach(el => {
el.value !== value && (el.checked || el.indeterminate) && !el.isDisabled && el.doCheck(false, true, false)
})
} else {
parent.children.forEach(el => {
el.value !== value && (el.checked || el.indeterminate) && !el.isDisabled && el.doCheck(false, true, false)
})
}
}
}
//
// @checked
// @isForcecheckedchecked
// @isSelfcascader-node
doCheck(checked, isForce = false, isSelf = false) {
let { config, level, children } = this
let flag = config.mutualExcluseLabel && config.mutualExcluseLabel >= level + 1 && isSelf && children.length !== 0
if (this.checked !== checked || flag || isForce) {
if (this.config.checkStrictly) {
this.checked = checked
this.mutualExclusion()
} else {
if (flag) {
if (!this.indeterminate && !this.checked) {
checked = true
}
if (this.indeterminate && !this.checked) {
checked = false
}
}
this.broadcast('check', checked)
this.setCheckState(checked)
this.emit('check')
}
}
}
}