Skip to content

Commit

Permalink
Merge pull request #2 from hug-sun-1/refactor/tree-1
Browse files Browse the repository at this point in the history
refactor(Tree): 实现树形结构化数据进行显示以及动态更新 hug-sun#464
  • Loading branch information
Lydanne authored Jan 30, 2021
2 parents 05ee0a3 + 86dc356 commit 224acbd
Show file tree
Hide file tree
Showing 25 changed files with 1,822 additions and 19 deletions.
7 changes: 7 additions & 0 deletions packages/element3/src/components/Tree/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ElTree from './src/Tree.vue'

ElTree.install = function (app) {
app.component(ElTree.name, ElTree)
}

export { ElTree }
20 changes: 20 additions & 0 deletions packages/element3/src/components/Tree/src/NodeContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import { TreeNode } from './entity/TreeNode'
import { h } from 'vue'
export default {
name: 'ElNodeContent',
props: {
node: {
required: true,
type: TreeNode
}
},
setup(props) {
return () => {
return h('span', props.node.label)
}
}
}
</script>
39 changes: 39 additions & 0 deletions packages/element3/src/components/Tree/src/Tree.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<el-tree-main
v-model="_modelValue"
:defaultNodeKey="_defaultNodeKey"
></el-tree-main>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import ElTreeMain from './TreeMain.vue'
/**
* Compatibility layer components designed for older APIs.
*/
export default defineComponent({
name: 'ElTree',
components: { ElTreeMain },
props: {
data: Array,
modelValue: Array,
defaultNodeKey: Object,
props: Object
},
emits: ['update:modelValue', 'update:data'],
computed: {
_modelValue: {
get() {
return this.modelValue ?? this.data
},
set(v) {
this.$emit('update:modelValue', v)
this.$emit('update:data', v)
}
},
_defaultNodeKey() {
return this.defaultNodeKey ?? this.props
}
}
})
</script>
39 changes: 39 additions & 0 deletions packages/element3/src/components/Tree/src/TreeMain.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="el-tree" role="Tree">
<el-tree-node v-for="child in rootChildren" :node="child" :key="child.id">
</el-tree-node>
<div class="el-tree__empty-block" v-if="tree.isEmpty">
<span class="el-tree__empty-text">{{ emptyText }}</span>
</div>
</div>
</template>

<script lang="ts">
import { computed, getCurrentInstance, provide } from 'vue'
import { t } from '../../../locale'
import ElTreeNode from './TreeNode.vue'
import { Tree } from './entity/Tree'
export default {
name: 'ElTreeMain',
components: { ElTreeNode },
props: {
modelValue: { type: Array, default: () => [] },
emptyText: { type: String, default: () => t('el.tree.emptyText') },
defaultNodeKey: Object,
indent: { type: Number, default: 18 }
},
emits: ['update:modelValue'],
setup(props, ctx) {
const elTree = getCurrentInstance().proxy
provide('elTree', elTree)
const tree = new Tree(props.modelValue, props.defaultNodeKey)
ctx.emit('update:modelValue', tree.rawNodesProxy)
const rootChildren = computed(() => tree.root.children)
return {
tree,
rootChildren
}
}
}
</script>
59 changes: 59 additions & 0 deletions packages/element3/src/components/Tree/src/TreeNode.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<div
class="el-tree-node"
role="TreeNode"
tabindex="-1"
:id="'TreeNode' + node.id"
:data-node-id="node.id"
>
<div
class="el-tree-node__content"
:style="{ 'padding-left': node.level * elTree.indent + 'px' }"
>
<span
v-if="node.asyncState === 'loading'"
class="el-tree-node__loading-icon el-icon-loading"
></span>
<el-node-content
class="el-tree-node__label"
:node="node"
></el-node-content>
</div>
<el-collapse-transition>
<div class="el-tree-node__children" role="group">
<el-tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
>
</el-tree-node>
</div>
</el-collapse-transition>
</div>
</template>

<script lang="ts">
import ElCollapseTransition from '../../../transitions/collapse-transition'
import ElNodeContent from './NodeContent.vue'
import { TreeNode } from './entity/TreeNode'
import { inject } from 'vue'
export default {
name: 'ElTreeNode',
components: {
ElCollapseTransition,
ElNodeContent
},
props: {
node: TreeNode
},
setup() {
const elTree = inject('elTree', { indent: 10 })
return {
elTree
}
}
}
</script>
53 changes: 53 additions & 0 deletions packages/element3/src/components/Tree/src/entity/Tree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { DefaultNodeKey, RawNodeBase } from '../types'
import { TreeNode } from './TreeNode'
import { TreeMapper } from './TreeMapper'

export class Tree<RawNode extends RawNodeBase> {
private _mapper: TreeMapper<RawNode>
private _defaultNodeKey: DefaultNodeKey<RawNode>

get root(): TreeNode {
return this._mapper.treeNode
}

get rootProxy(): TreeNode {
return this._mapper.treeNodeProxy
}

get rawRootProxy(): RawNode {
return this._mapper.rawNodeProxy
}

get rawNodesProxy(): RawNode[] {
return this.rawRootProxy[this._defaultNodeKey.children]
}

get isEmpty() {
return this.root.children.length === 0
}

constructor(rawNodes: RawNode[], defaultNodeKey: DefaultNodeKey<RawNode>) {
this._defaultNodeKey = Object.assign(
{
id: 'id',
label: 'label',
children: 'children',
isDisabled: 'isDisabled',
isAsync: 'isAsync',
isChecked: 'isChecked',
isVisible: 'isVisible',
isExpanded: 'isExpanded',
isLeaf: 'isLeaf'
},
defaultNodeKey
)

this._mapper = new TreeMapper<RawNode>(
{
[this._defaultNodeKey.label]: 'ROOT',
[this._defaultNodeKey.children]: rawNodes
} as RawNode,
this._defaultNodeKey
)
}
}
Loading

0 comments on commit 224acbd

Please sign in to comment.