Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
Element
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
CI / CD Analytics
Repository Analytics
Value Stream Analytics
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
林焕东
Element
Commits
5deb201d
Commit
5deb201d
authored
Oct 18, 2016
by
杨奕
Committed by
GitHub
Oct 18, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #470 from furybean/tree-new
Improve Tree
parents
68fbcc13
785bed20
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
152 additions
and
65 deletions
+152
-65
examples/docs/zh-cn/tree.md
examples/docs/zh-cn/tree.md
+3
-1
packages/theme-default/src/tree.css
packages/theme-default/src/tree.css
+5
-1
packages/tree/src/model/node.js
packages/tree/src/model/node.js
+70
-35
packages/tree/src/model/tree.js
packages/tree/src/model/tree.js
+2
-4
packages/tree/src/transition.js
packages/tree/src/transition.js
+1
-1
packages/tree/src/tree-node.vue
packages/tree/src/tree-node.vue
+60
-20
packages/tree/src/tree.vue
packages/tree/src/tree.vue
+11
-3
No files found.
examples/docs/zh-cn/tree.md
View file @
5deb201d
...
...
@@ -235,6 +235,8 @@
| props | 配置选项,具体看下表 | object | — | — |
| load | 加载子树数据的方法 | function(node, resolve) | — | — |
| show-checkbox | 节点是否可被选择 | boolean | — | false |
| render-content | 树节点的内容区的渲染 Function,会传入两个参数,h 与 { node: node }。 | Function | - | - |
| highlight-current | 是否高亮当前选中节点,默认值是 false。| boolean | - | false |
### props
...
...
@@ -253,5 +255,5 @@
### Events
| 事件名称 | 说明 | 回调参数 |
|---------- |-------- |---------- |
| node-click | 节点被点击时的回调 |
传递给
`data`
属性的数组中该节点所对应的对象
|
| node-click | 节点被点击时的回调 |
共三个参数,依次为:传递给
`data`
属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。
|
| check-change | 节点选中状态发生变化时的回调 | 共三个参数,依次为:传递给
`data`
属性的数组中该节点所对应的对象、
<br>
节点本身是否被选中、节点的子树中是否有被选中的节点 |
packages/theme-default/src/tree.css
View file @
5deb201d
...
...
@@ -3,7 +3,6 @@
@component-namespace
el
{
@b
tree
{
overflow
:
auto
;
cursor
:
default
;
background
:
#ffffff
;
border
:
1px
solid
#d3dce6
;
...
...
@@ -82,6 +81,11 @@
}
}
}
.el-tree--highlight-current
.el-tree-node.is-current
>
.el-tree-node__content
{
background-color
:
#eff7ff
;
}
.collapse-transition
{
transition
:
0.3s
height
ease-in-out
,
0.3s
padding-top
ease-in-out
,
0.3s
padding-bottom
ease-in-out
;
}
packages/tree/src/model/node.js
View file @
5deb201d
let
i
dSeed
=
0
;
let
nodeI
dSeed
=
0
;
import
objectAssign
from
'
object-assign
'
;
const
reInitChecked
=
function
(
node
)
{
const
siblings
=
node
.
child
ren
;
const
siblings
=
node
.
child
Nodes
;
let
all
=
true
;
let
none
=
true
;
...
...
@@ -42,7 +42,7 @@ const getPropertyFromData = function(node, prop) {
export
default
class
Node
{
constructor
(
options
)
{
this
.
id
=
i
dSeed
++
;
this
.
id
=
nodeI
dSeed
++
;
this
.
text
=
null
;
this
.
checked
=
false
;
this
.
indeterminate
=
false
;
...
...
@@ -61,7 +61,7 @@ export default class Node {
// internal
this
.
level
=
-
1
;
this
.
loaded
=
false
;
this
.
child
ren
=
[];
this
.
child
Nodes
=
[];
this
.
loading
=
false
;
if
(
this
.
parent
)
{
...
...
@@ -74,8 +74,17 @@ export default class Node {
}
setData
(
data
)
{
if
(
!
Array
.
isArray
(
data
)
&&
!
data
.
$treeNodeId
)
{
Object
.
defineProperty
(
data
,
'
$treeNodeId
'
,
{
value
:
this
.
id
,
enumerable
:
false
,
configurable
:
false
,
writable
:
false
});
}
this
.
data
=
data
;
this
.
child
ren
=
[];
this
.
child
Nodes
=
[];
let
children
;
if
(
this
.
level
===
-
1
&&
this
.
data
instanceof
Array
)
{
...
...
@@ -85,14 +94,7 @@ export default class Node {
}
for
(
let
i
=
0
,
j
=
children
.
length
;
i
<
j
;
i
++
)
{
const
child
=
children
[
i
];
this
.
insertChild
(
new
Node
({
data
:
child
,
parent
:
this
,
lazy
:
this
.
lazy
,
load
:
this
.
load
,
props
:
this
.
props
}));
this
.
insertChild
({
data
:
children
[
i
]
});
}
}
...
...
@@ -107,26 +109,47 @@ export default class Node {
insertChild
(
child
,
index
)
{
if
(
!
child
)
throw
new
Error
(
'
insertChild error: child is required.
'
);
if
(
!
child
instanceof
Node
)
{
throw
new
Error
(
'
insertChild error: child should an instance of Node.
'
);
if
(
!
(
child
instanceof
Node
))
{
objectAssign
(
child
,
{
parent
:
this
,
lazy
:
this
.
lazy
,
load
:
this
.
load
,
props
:
this
.
props
});
child
=
new
Node
(
child
);
}
child
.
parent
=
this
;
child
.
level
=
this
.
level
+
1
;
if
(
typeof
index
===
'
undefined
'
)
{
this
.
child
ren
.
push
(
child
);
this
.
child
Nodes
.
push
(
child
);
}
else
{
this
.
child
ren
.
splice
(
index
,
0
,
child
);
this
.
child
Nodes
.
splice
(
index
,
0
,
child
);
}
}
removeChild
(
child
)
{
const
index
=
this
.
child
ren
.
indexOf
(
child
);
const
index
=
this
.
child
Nodes
.
indexOf
(
child
);
if
(
index
>
-
1
)
{
child
.
parent
=
null
;
this
.
children
.
splice
(
child
,
index
);
this
.
childNodes
.
splice
(
index
,
1
);
}
}
removeChildByData
(
data
)
{
let
nodeIndex
=
-
1
;
let
targetNode
=
null
;
this
.
childNodes
.
forEach
((
node
,
index
)
=>
{
if
(
node
.
data
===
data
)
{
nodeIndex
=
index
;
targetNode
=
node
;
}
});
if
(
nodeIndex
>
-
1
)
{
targetNode
.
parent
=
null
;
this
.
childNodes
.
splice
(
nodeIndex
,
1
);
}
}
...
...
@@ -147,13 +170,7 @@ export default class Node {
doCreateChildren
(
array
,
defaultProps
=
{})
{
array
.
forEach
((
item
)
=>
{
const
node
=
new
Node
(
objectAssign
({
data
:
item
,
lazy
:
this
.
lazy
,
load
:
this
.
load
,
props
:
this
.
props
},
defaultProps
));
this
.
insertChild
(
node
);
this
.
insertChild
(
objectAssign
({
data
:
item
},
defaultProps
));
});
}
...
...
@@ -170,9 +187,9 @@ export default class Node {
}
hasChild
()
{
const
child
ren
=
this
.
children
;
const
child
Nodes
=
this
.
childNodes
;
if
(
!
this
.
lazy
||
(
this
.
lazy
===
true
&&
this
.
loaded
===
true
))
{
return
child
ren
&&
children
.
length
>
0
;
return
child
Nodes
&&
childNodes
.
length
>
0
;
}
return
true
;
}
...
...
@@ -183,9 +200,9 @@ export default class Node {
const
handleDeep
=
()
=>
{
if
(
deep
)
{
const
child
ren
=
this
.
children
;
for
(
let
i
=
0
,
j
=
child
ren
.
length
;
i
<
j
;
i
++
)
{
const
child
=
child
ren
[
i
];
const
child
Nodes
=
this
.
childNodes
;
for
(
let
i
=
0
,
j
=
child
Nodes
.
length
;
i
<
j
;
i
++
)
{
const
child
=
child
Nodes
[
i
];
child
.
setChecked
(
value
!==
false
,
deep
);
}
}
...
...
@@ -225,15 +242,33 @@ export default class Node {
return
data
[
children
];
}
updateChildren
()
{
const
newData
=
this
.
getChildren
()
||
[];
const
oldData
=
this
.
childNodes
.
map
((
node
)
=>
node
.
data
);
const
newDataMap
=
{};
const
newNodes
=
[];
newData
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
$treeNodeId
)
{
newDataMap
[
item
.
$treeNodeId
]
=
{
index
,
data
:
item
};
}
else
{
newNodes
.
push
({
index
,
data
:
item
});
}
});
oldData
.
forEach
((
item
)
=>
{
if
(
!
newDataMap
[
item
.
$treeNodeId
])
this
.
removeChildByData
(
item
);
});
newNodes
.
forEach
(({
index
,
data
})
=>
this
.
insertChild
({
data
},
index
));
}
loadData
(
callback
,
defaultProps
=
{})
{
if
(
this
.
lazy
===
true
&&
this
.
load
&&
!
this
.
loaded
)
{
this
.
loading
=
true
;
const
loadFn
=
this
.
load
;
const
resolve
=
(
children
)
=>
{
this
.
loaded
=
true
;
this
.
loading
=
false
;
this
.
child
ren
=
[];
this
.
child
Nodes
=
[];
this
.
doCreateChildren
(
children
,
defaultProps
);
...
...
@@ -242,7 +277,7 @@ export default class Node {
}
};
loadFn
(
this
,
resolve
);
this
.
load
(
this
,
resolve
);
}
else
{
if
(
callback
)
{
callback
.
call
(
this
);
...
...
packages/tree/src/model/tree.js
View file @
5deb201d
...
...
@@ -8,8 +8,6 @@ export default class Tree {
}
}
this
.
_isTree
=
true
;
this
.
root
=
new
Node
({
data
:
this
.
data
,
lazy
:
this
.
lazy
,
...
...
@@ -28,9 +26,9 @@ export default class Tree {
getCheckedNodes
(
leafOnly
)
{
const
checkedNodes
=
[];
const
walk
=
function
(
node
)
{
const
child
ren
=
node
.
root
?
node
.
root
.
children
:
node
.
children
;
const
child
Nodes
=
node
.
root
?
node
.
root
.
childNodes
:
node
.
childNodes
;
child
ren
.
forEach
(
function
(
child
)
{
child
Nodes
.
forEach
(
function
(
child
)
{
if
((
!
leafOnly
&&
child
.
checked
)
||
(
leafOnly
&&
child
.
isLeaf
&&
child
.
checked
))
{
checkedNodes
.
push
(
child
.
data
);
}
...
...
packages/tree/src/transition.js
View file @
5deb201d
...
...
@@ -58,7 +58,7 @@ class Transition {
el
.
style
.
paddingTop
=
el
.
dataset
.
oldPaddingTop
;
el
.
style
.
paddingBottom
=
el
.
dataset
.
oldPaddingBottom
;
}
}
;
}
export
default
{
functional
:
true
,
...
...
packages/tree/src/tree-node.vue
View file @
5deb201d
<
template
>
<div
class=
"el-tree-node"
:class=
"
{ expanded: childrenRendered
&&
expanded }">
<div
class=
"el-tree-node__content"
:style=
"
{ 'padding-left': node.level * 16 + 'px' }"
@
click.stop=
"handleClick"
:class=
"
{ expanded: childNodeRendered
&&
expanded, 'is-current': $tree.currentNode === _self }">
<div
class=
"el-tree-node__content"
:style=
"
{ 'padding-left': node.level * 16 + 'px' }"
@click="handleExpandIconClick">
<span
class=
"el-tree-node__expand-icon"
:class=
"
{ 'is-leaf': node.isLeaf, expanded: !node.isLeaf
&&
expanded }"
>
</span>
<el-checkbox
v-if=
"showCheckbox"
:indeterminate=
"node.indeterminate"
v-model=
"node.checked"
@
change=
"handleCheckChange"
@
click.native=
"handleUserClick"
></el-checkbox>
<span
class=
"el-tree-node__expand-icon"
:class=
"
{ 'is-leaf': node.isLeaf, expanded: !node.isLeaf
&&
expanded }">
</span>
<el-checkbox
v-if=
"showCheckbox"
v-model=
"node.checked"
:indeterminate=
"node.indeterminate"
@
change=
"handleCheckChange"
@
click.native=
"handleUserClick"
>
</el-checkbox>
<span
v-if=
"node.loading"
class=
"el-tree-node__icon el-icon-loading"
>
class=
"el-tree-node__icon el-icon-loading"
>
</span>
<
span
class=
"el-tree-node__label"
v-html=
"node.label"
></span
>
<
node-content
:node=
"node"
></node-content
>
</div>
<collapse-transition>
<div
class=
"el-tree-node__children"
<div
class=
"el-tree-node__children"
v-show=
"expanded"
>
<el-tree-node
v-for=
"child in node.children"
:node=
"child"
></el-tree-node>
<el-tree-node
:render-content=
"renderContent"
v-for=
"child in node.childNodes"
:node=
"child"
>
</el-tree-node>
</div>
</collapse-transition>
</div>
</
template
>
<
script
type=
"text/
ecmascript-6
"
>
<
script
type=
"text/
jsx
"
>
import
CollapseTransition
from
'
./transition
'
;
export
default
{
...
...
@@ -34,18 +47,35 @@
default
()
{
return
{};
}
}
},
props
:
{},
renderContent
:
Function
},
components
:
{
CollapseTransition
CollapseTransition
,
NodeContent
:
{
props
:
{
node
:
{
required
:
true
}
},
render
(
h
)
{
const
parent
=
this
.
$parent
;
return
(
parent
.
renderContent
?
parent
.
renderContent
.
call
(
parent
.
_renderProxy
,
h
,
{
_self
:
parent
.
$parent
.
$vnode
.
context
,
node
:
this
.
node
})
:
<
span
class
=
"
el-tree-node__label
"
>
{
this
.
node
.
label
}
<
/span
>
);
}
}
},
data
()
{
return
{
$tree
:
null
,
expanded
:
false
,
child
ren
Rendered
:
false
,
child
Node
Rendered
:
false
,
showCheckbox
:
false
,
oldChecked
:
null
,
oldIndeterminate
:
null
...
...
@@ -71,21 +101,25 @@
this
.
indeterminate
=
indeterminate
;
},
handleClick
()
{
this
.
$tree
.
currentNode
=
this
;
},
handleExpandIconClick
(
event
)
{
let
target
=
event
.
target
;
if
(
target
.
tagName
.
toUpperCase
()
!==
'
DIV
'
&&
target
.
parentNode
.
nodeName
.
toUpperCase
()
!==
'
DIV
'
||
target
.
nodeName
.
toUpperCase
()
===
'
LABLE
'
)
return
;
target
.
nodeName
.
toUpperCase
()
===
'
LABEL
'
)
return
;
if
(
this
.
expanded
)
{
this
.
node
.
collapse
();
this
.
expanded
=
false
;
}
else
{
this
.
node
.
expand
(()
=>
{
this
.
expanded
=
true
;
this
.
child
ren
Rendered
=
true
;
this
.
child
Node
Rendered
=
true
;
});
}
this
.
$tree
.
$emit
(
'
node-click
'
,
this
.
node
.
data
);
this
.
$tree
.
$emit
(
'
node-click
'
,
this
.
node
.
data
,
this
.
node
,
this
);
},
handleUserClick
()
{
...
...
@@ -111,6 +145,12 @@
}
const
tree
=
this
.
$tree
;
const
props
=
this
.
props
||
{};
const
childrenKey
=
props
[
'
children
'
]
||
'
children
'
;
this
.
$watch
(
`node.data.
${
childrenKey
}
`
,
()
=>
{
this
.
node
.
updateChildren
();
});
if
(
!
tree
)
{
console
.
warn
(
'
Can not find node
\'
s tree.
'
);
...
...
packages/tree/src/tree.vue
View file @
5deb201d
<
template
>
<div
class=
"el-tree"
>
<el-tree-node
v-for=
"child in tree.root.children"
:node=
"child"
></el-tree-node>
<div
class=
"el-tree"
:class=
"
{ 'el-tree--highlight-current': highlightCurrent }">
<el-tree-node
v-for=
"child in tree.root.childNodes"
:node=
"child"
:props=
"props"
:render-content=
"renderContent"
>
</el-tree-node>
</div>
</
template
>
...
...
@@ -14,6 +19,7 @@
data
:
{
type
:
Array
},
renderContent
:
Function
,
showCheckbox
:
{
type
:
Boolean
,
default
:
false
...
...
@@ -31,6 +37,7 @@
type
:
Boolean
,
default
:
false
},
highlightCurrent
:
Boolean
,
load
:
{
type
:
Function
}
...
...
@@ -49,7 +56,8 @@
data
()
{
return
{
tree
:
{}
tree
:
{},
currentNode
:
null
};
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment