我有一个类似的数据结构
[
{"name":"foo", "links":["a", "b", "c"]},
{"name":"bar", "links":["d", "e", "f"]}
]
Run Code Online (Sandbox Code Playgroud)
我想列一个清单
<ul>
<li> foo </li>
<li> bar </li>
</ul>
Run Code Online (Sandbox Code Playgroud)
当我点击foo时,扩展为
<ul>
<li> foo
<ul>
<li> a </li>
<li> b </li>
<li> c </li>
</ul>
</li>
<li> bar </li>
</ul>
Run Code Online (Sandbox Code Playgroud)
我想用d3.js这样做.制作热门列表非常简单有趣:
toplist = d3.select("body").append("ul");
toplist.selectAll("li")
.data(data)
.enter()
.append("li")
.text(function(d){return d.name;})
Run Code Online (Sandbox Code Playgroud)
添加子列表甚至很容易:
items = toplist.append("ul")
.selectAll("li")
.data(function(d){return d.links})
.enter()
.append("li")
.text(function(d){return d})
Run Code Online (Sandbox Code Playgroud)
我可以on("click"..在每个li中添加一个toplist,比如
toplist.selectAll("li")
.data(data)
.enter()
.append("li")
.text(function(d){return d.name;})
.on("click", expand)
Run Code Online (Sandbox Code Playgroud)
并将子列表代码移动到名为expand的函数中.看起来像
function expand(d,i){
Run Code Online (Sandbox Code Playgroud)
然后在其中包含上述items = ...代码.
麻烦的是,这则两侧展开的foo,并bar在同一时间.
如何为foolist元素提供单独的click事件,bar仅扩展该元素?本质上,我需要传递expand数据元素的索引,并让它只对DOM的特定部分进行操作.
任何帮助,将不胜感激!
expand调用时,您拥有所需的一切.所述this上下文是被点击的li元素,并且d是相关联的数据.如果您只想展开(而不是在展开和折叠之间切换),那么您可以通过选择以下内容来创建子列表:
function expand(d) {
d3.select(this)
.on("click", null)
.append("ul")
.selectAll("li")
.data(d.links)
.enter().append("li")
.text(function(d) { return d; });
}
Run Code Online (Sandbox Code Playgroud)
请注意,expand还会从单击的项目中删除单击处理程序; 单击两次时,您不想再次添加列表.
如果要在展开和删除之间切换,则需要跟踪某个状态:子菜单是打开还是关闭.您可以通过在d(d.open例如)上存储布尔值来执行此操作,或者您可以通过查询DOM以查看子菜单是否已存在来执行此操作:d3.select(this).select("ul").empty().
另一种可以做到这一点的方法是提前创建所有子菜单,然后通过displaystyle属性切换可见性.如果您拥有所有可用数据,这是最简单的选择; 如果您异步加载链接数据,我可能只会动态创建子菜单.