element/packages/tree/src/tree.vue

258 lines
7.4 KiB
Vue
Raw Normal View History

2016-07-27 06:15:02 +00:00
<template>
<div
class="el-tree"
:class="{ 'el-tree--highlight-current': highlightCurrent }"
role="tree"
>
<el-tree-node
v-for="child in root.childNodes"
:node="child"
:props="props"
:key="getNodeKey(child)"
2017-01-14 08:02:52 +00:00
:render-content="renderContent"
@node-expand="handleNodeExpand">
</el-tree-node>
<div class="el-tree__empty-block" v-if="!root.childNodes || root.childNodes.length === 0">
<span class="el-tree__empty-text">{{ emptyText }}</span>
</div>
2016-07-27 06:15:02 +00:00
</div>
</template>
2017-03-17 03:35:27 +00:00
<script>
import TreeStore from './model/tree-store';
2017-10-11 10:00:58 +00:00
import ElTreeNode from './tree-node.vue';
import {t} from 'element-ui/src/locale';
2017-01-14 08:02:52 +00:00
import emitter from 'element-ui/src/mixins/emitter';
2016-07-27 06:15:02 +00:00
export default {
name: 'ElTree',
2016-07-27 06:15:02 +00:00
2017-01-14 08:02:52 +00:00
mixins: [emitter],
components: {
2017-10-11 10:00:58 +00:00
ElTreeNode
2017-01-14 08:02:52 +00:00
},
data() {
return {
store: null,
root: null,
currentNode: null,
treeItems: null,
checkboxItems: []
2017-01-14 08:02:52 +00:00
};
},
2016-07-27 06:15:02 +00:00
props: {
data: {
type: Array
},
emptyText: {
type: String,
2016-11-17 07:37:04 +00:00
default() {
return t('el.tree.emptyText');
}
},
nodeKey: String,
checkStrictly: Boolean,
defaultExpandAll: Boolean,
expandOnClickNode: {
type: Boolean,
default: true
},
2017-07-28 08:54:07 +00:00
checkDescendants: {
type: Boolean,
default: false
},
autoExpandParent: {
type: Boolean,
default: true
},
defaultCheckedKeys: Array,
defaultExpandedKeys: Array,
renderContent: Function,
2016-07-27 06:15:02 +00:00
showCheckbox: {
type: Boolean,
default: false
},
props: {
default() {
return {
children: 'children',
label: 'label',
2017-07-19 10:36:26 +00:00
icon: 'icon',
disabled: 'disabled'
2016-07-27 06:15:02 +00:00
};
}
},
lazy: {
type: Boolean,
default: false
},
highlightCurrent: Boolean,
load: Function,
2017-01-14 08:02:52 +00:00
filterNodeMethod: Function,
2017-02-08 03:49:54 +00:00
accordion: Boolean,
indent: {
type: Number,
default: 18
2017-02-08 03:49:54 +00:00
}
2016-07-27 06:15:02 +00:00
},
computed: {
children: {
set(value) {
this.data = value;
},
get() {
return this.data;
}
},
treeItemArray() {
return Array.prototype.slice.call(this.treeItems);
2016-07-27 06:15:02 +00:00
}
},
2016-10-08 05:58:31 +00:00
watch: {
defaultCheckedKeys(newVal) {
this.store.defaultCheckedKeys = newVal;
this.store.setDefaultCheckedKey(newVal);
},
defaultExpandedKeys(newVal) {
this.store.defaultExpandedKeys = newVal;
this.store.setDefaultExpandedKeys(newVal);
},
data(newVal) {
this.store.setData(newVal);
},
checkboxItems(val) {
Array.prototype.forEach.call(val, (checkbox) => {
checkbox.setAttribute('tabindex', -1);
});
2016-10-08 05:58:31 +00:00
}
},
2016-07-27 06:15:02 +00:00
methods: {
filter(value) {
if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
this.store.filter(value);
},
getNodeKey(node, index) {
const nodeKey = this.nodeKey;
if (nodeKey && node) {
return node.data[nodeKey];
}
return index;
},
2016-07-27 06:15:02 +00:00
getCheckedNodes(leafOnly) {
return this.store.getCheckedNodes(leafOnly);
},
getCheckedKeys(leafOnly) {
return this.store.getCheckedKeys(leafOnly);
},
getCurrentNode() {
const currentNode = this.store.getCurrentNode();
return currentNode ? currentNode.data : null;
},
getCurrentKey() {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in getCurrentKey');
const currentNode = this.getCurrentNode();
return currentNode ? currentNode[this.nodeKey] : null;
},
setCheckedNodes(nodes, leafOnly) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCheckedNodes');
this.store.setCheckedNodes(nodes, leafOnly);
},
setCheckedKeys(keys, leafOnly) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCheckedKeys');
this.store.setCheckedKeys(keys, leafOnly);
2016-11-28 10:57:09 +00:00
},
setChecked(data, checked, deep) {
this.store.setChecked(data, checked, deep);
2017-01-14 08:02:52 +00:00
},
setCurrentNode(node) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentNode');
this.store.setUserCurrentNode(node);
},
setCurrentKey(key) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentKey');
this.store.setCurrentNodeKey(key);
},
handleNodeExpand(nodeData, node, instance) {
this.broadcast('ElTreeNode', 'tree-node-expand', node);
this.$emit('node-expand', nodeData, node, instance);
2017-07-21 08:25:28 +00:00
},
updateKeyChildren(key, data) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in updateKeyChild');
this.store.updateChildren(key, data);
},
initTabindex() {
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
const checkedItem = this.$el.querySelectorAll('.is-checked[role=treeitem]');
if (checkedItem.length) {
checkedItem[0].setAttribute('tabindex', 0);
return;
}
this.treeItems[0] && this.treeItems[0].setAttribute('tabindex', 0);
},
handelKeydown(ev) {
const currentItem = ev.target;
2017-11-15 03:03:02 +00:00
if (currentItem.className.indexOf('el-tree-node') === -1) return;
ev.preventDefault();
const keyCode = ev.keyCode;
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
const currentIndex = this.treeItemArray.indexOf(currentItem);
let nextIndex;
2017-11-12 03:56:41 +00:00
if ([38, 40].indexOf(keyCode) > -1) { // up、down
if (keyCode === 38) { // up
nextIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
} else {
nextIndex = (currentIndex < this.treeItemArray.length - 1) ? currentIndex + 1 : 0;
}
this.treeItemArray[nextIndex].focus(); // 选中
}
const hasInput = currentItem.querySelector('[type="checkbox"]');
2017-11-12 03:56:41 +00:00
if ([37, 39].indexOf(keyCode) > -1) { // left、right 展开
currentItem.click(); // 选中
}
2017-11-12 03:56:41 +00:00
if ([13, 32].indexOf(keyCode) > -1) { // space enter选中checkbox
if (hasInput) {
hasInput.click();
}
}
2016-07-27 06:15:02 +00:00
}
2017-01-14 08:02:52 +00:00
},
created() {
this.isTree = true;
this.store = new TreeStore({
key: this.nodeKey,
data: this.data,
lazy: this.lazy,
props: this.props,
load: this.load,
currentNodeKey: this.currentNodeKey,
checkStrictly: this.checkStrictly,
2017-07-28 08:54:07 +00:00
checkDescendants: this.checkDescendants,
2017-01-14 08:02:52 +00:00
defaultCheckedKeys: this.defaultCheckedKeys,
defaultExpandedKeys: this.defaultExpandedKeys,
autoExpandParent: this.autoExpandParent,
defaultExpandAll: this.defaultExpandAll,
filterNodeMethod: this.filterNodeMethod
});
this.root = this.store.root;
},
mounted() {
this.initTabindex();
this.$el.addEventListener('keydown', this.handelKeydown);
},
updated() {
this.treeItems = this.$el.querySelectorAll('[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
2016-07-27 06:15:02 +00:00
}
};
</script>