UNPKG

kui-vue

Version:

A high quality UI Toolkit built on Vue.js 2.0

254 lines (238 loc) 7.6 kB
import TreeNode from './node.jsx' import { getChild } from '../_tool/utils.js' import cloneVNode from '../_tool/clone.js' export default { name: 'Tree', props: { data: Array, selectedKeys: Array, expandedKeys: Array, expandedAll: Boolean, checkedKeys: Array, checkable: Boolean, draggable: Boolean, showLine: Boolean, showIcon: { type: Boolean, default: true }, showExtra: { type: Boolean, default: false }, multiple: { type: Boolean, default: false }, checkStrictly: Boolean, directory: Boolean, }, provide() { return { Tree: this, } }, data() { return { defaultData: this.data || [], defaultSelectedKeys: this.selectedKeys || [], defaultExpandedKeys: this.expandedKeys || [], defaultCheckedKeys: this.checkedKeys || [], ctrlKeyEntered: false, halfCheckedKeys: [], dragNode: null, dragParentNode: null, } }, watch: { data(val, Oval) { this.defaultData = val || [] }, selectedKeys(val, Oval) { this.defaultSelectedKeys = val || [] }, expandedKeys(val, Oval) { this.defaultExpandedKeys = val || [] }, checkedKeys(val, Oval) { this.defaultCheckedKeys = val || [] }, }, created() { //Init key // (this.defaultData || []).forEach(item => { // // this.setKeys(item); // }); //Init half check this.setCheckHalf() }, mounted() { window.addEventListener('keydown', this.handleKeyDown); }, beforeDestroy() { window.removeEventListener('keydown', this.handleKeyDown); window.removeEventListener('keyup', this.handleKeyUp); }, methods: { handleKeyDown(event) { // console.log(event) if (event.ctrlKe || event.metaKey) { this.ctrlKeyEntered = true; } window.addEventListener('keyup', this.handleKeyUp); }, handleKeyUp(event) { if (!event.ctrlKey && event.metaKey) { this.ctrlKeyEntered = false; } }, setCheckHalf() { this.checkable && !this.checkStrictly && (this.defaultCheckedKeys || []).forEach(key => { this.setParentHalf(this.defaultData, key) }) }, // setKeys({ children = [] }, key = 'n') { // for (let i = 0; i < children.length; i++) { // let item = children[i] // item.key = item.key || `${key}_${i}` // this.setKeys(item, item.key) // } // }, setParentHalf(data = [], key) { for (let i = 0; i < data.length; i++) { let item = data[i] let { children = [], disabled } = item let keys = children.filter(child => !child.disabled).map(child => child.key) if (keys.indexOf(key) >= 0 && this.defaultCheckedKeys.indexOf(item.key) < 0) { //符合要求 this.halfCheckedKeys.push(item.key) this.setParentHalf(this.defaultData, item.key) break; } else { this.setParentHalf(children, key) } } }, onCheck(checked, key, node) { this.$emit('check', { checkedKeys: this.defaultCheckedKeys, checked, node }) }, onSelect(key, node) { let { defaultSelectedKeys, ctrlKeyEntered, multiple } = this let index = defaultSelectedKeys.indexOf(key) if (multiple) { if (ctrlKeyEntered) { index > -1 ? defaultSelectedKeys.splice(index, 1) : defaultSelectedKeys.push(key) } else { index > -1 ? defaultSelectedKeys.splice(index, 1) : defaultSelectedKeys.push(key) } } else { defaultSelectedKeys = index > -1 ? [] : [key] } // if (ctrlKeyEntered) { // index > -1 ? defaultSelectedKeys.splice(index, 1) : defaultSelectedKeys.push(key) // } else { // defaultSelectedKeys = index > -1 ? [] : [key] // } this.defaultSelectedKeys = defaultSelectedKeys this.$emit('select', { selectedKeys: defaultSelectedKeys, selected: index < 0, node }) }, onExpand(key, item, vnode) { let hasLoad = 'loadData' in this.$listeners || 'load-data' in this.$listeners if (item.children && item.children.length) { let { defaultExpandedKeys } = this let index = defaultExpandedKeys.indexOf(key) index > -1 ? defaultExpandedKeys.splice(index, 1) : defaultExpandedKeys.push(key) this.defaultExpandedKeys = defaultExpandedKeys this.$emit('expand', { expandedKeys: defaultExpandedKeys, expanded: index < 0, node: item, vnode }) } else if (hasLoad && !item.isLeaf && !vnode.loading) { vnode.loading = true this.$emit('load-data', item, child => { vnode.loading = false item.children = child this.defaultExpandedKeys.push(vnode.$vnode.key) this.$emit('expand', { expandedKeys: this.defaultExpandedKeys, expanded: true, node: item, vnode }) }) } }, // onDragStart(e, { node, parent }) { onDragStart(event, { defaultData, VNode }) { this.dragNode = defaultData this.dragParentNode = VNode let index = this.defaultExpandedKeys.indexOf(defaultData.key) if (index > -1) { this.defaultExpandedKeys.splice(index, 1) } this.$emit('dragstart', { event, node: defaultData }) }, onDragEnd(event, { node, parent }) { this.$emit('dragend', { event, node }) }, onDragEnter(event, { node, parent }) { this.$emit('dragenter', { event, node, expandedKeys: this.defaultExpandedKeys }) }, onDragLeave(event, { node, parent }) { this.$emit('dragleave', { event, node }) }, onDrop(event, { node }) { let dragParentNode = this.dragParentNode.defaultData let { dragNode } = this if (dragNode && node.key != dragNode.key && node.key != dragParentNode.key) { //remove self let index = dragParentNode.children.indexOf(dragNode) dragParentNode.children.splice(index, 1) this.dragParentNode.reload = false // if not children ,remove expand key if (!dragParentNode.children.length) { let index = this.defaultExpandedKeys.indexOf(dragParentNode.key) index > -1 && this.defaultExpandedKeys.splice(index, 1) } this.dragParentNode.reload = true // append self if (!node.children || !node.children.length) { node.children = []; this.defaultExpandedKeys.indexOf(node.key) < 0 && this.defaultExpandedKeys.push(node.key) } let keys = node.children.map(i => i.key) if (keys.indexOf(node.key) < 0) { node.children.push(dragNode) } } this.$emit('drop', { event, node, dragNode }) this.dragNode = null this.dragParentNode = null }, renderChild() { let { defaultData, $slots } = this let childs = getChild($slots.default) if (childs.length) { return childs.map((vnode, i) => { vnode.data.key = vnode.data.key || `n_${i}` let ele = cloneVNode(vnode) return ele; }) } return defaultData.map((item, i) => { const key = item.key || `n_${i}` item.key = key return <TreeNode data={item} key={key} /> }) } }, render() { let { showLine, directory } = this return (<div class={["k-tree", { 'k-tree-show-line': showLine, 'k-tree-directory': directory }]}> {this.renderChild()} </div>) } }