给人印象中,树组件是非常令人畏惧的一个组件,超级复杂,超级难写。但使用avalon2来做,这却是级其简单的一件事。首先从样式入做,无序列表是天然可用的树结构,几个UL元素套在一起,它们就自然处理好缩进问题。换言之,我们用UL元素作为树的节点,那么树组件内部也需要存在树组件,需要形成递归结构。avalon2的slot机制又是出场的时候了。
因此我们的树的结构大概是
树
子树
子树
子树
此外,树拥有还有折叠子树的功能,这好办,我们使用ms-visible实现隐藏显示子树。通过ms-click来为ms-visible传参。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../dist/avalon.js"></script>
</head>
<body>
<blockquote>
<div ms-controller="tree">
<wbr ms-widget="{is:'tree',tree: @data}" />
</div>
<script>
function heredoc(fn) {
return fn.toString().replace(/^[^\/]+\/\*!?\s?/, '').
replace(/\*\/[^\/]+$/, '').trim().replace(/>\s*</g, '><')
}
var treeID = 0
avalon.component('tree', {
template: heredoc(function () {
/*
<ul>
<li ms-for="(index, el) in @tree | get(0)">{{el.text}}
<span ms-click='@openSubTree(el)' ms-text="@changeIcon(el)"></span>
<div ms-visible="el.open" ms-html="@renderSubTree(el)">
</div>
</li>
</ul>
*/
}),
defaults: {
tree: [],
renderSubTree: function (el) {
return el.subtree.length ? '<wbr ms-widget="{is:"tree", $id:"tree_' + (++treeID) + '", tree: el.subtree}" />' : ''
},
openSubTree: function (el) {
el.open = !el.open
},
changeIcon: function (el) {
return el.open && el.subtree.length ? '[-]' : '[+]'
}
}
})
avalon.define({
$id: "tree",
data: [
{text: "aaa", open: 1, subtree: [
{text: 1111, open: 1, subtree: []},
{text: 2222, open: 1, subtree: [
{text: 777, open: 1, subtree: []}
]},
{text: 3333, open: 1, subtree: [
{text: 8888, open: 1, subtree: []},
{text: 9999, open: 1, subtree: [
{text: '司徒正美', open: 1, subtree: []}
]}
]}
]},
{text: "bbb", open: 1, subtree: [
{text: 4444, open: 1, subtree: []},
{text: 5555, open: 1, subtree: []},
{text: 6666, open: 1, subtree: []}
]},
{text: "ccc", open: 1, subtree: []},
{text: "ddd", open: 1, subtree: []},
{text: "eee", open: 1, subtree: [
{text: 1234, open: 1, subtree: []}
]},
{text: "fff", open: 1, subtree: []}
]
})
</script>
</blockquote>
</body>
</html>
看,我们的树组件一下子就出来,虽然看起来非常朴素,但的确是树,如果找设计师美化一下,添加些好看的ICON,完全是ztree没有什么两样。当然我们也可以照搬ztree的图标。最重要的,代码太少了,维护起来超方便。