话不多说,先上图:
点我查看演示
实现技术要点
- 目录结构层级的不可确定性;
此处应当使用递归遍历的方式遍历数据对象;
依据每次遍历的结果生成一个节点;
贴代码:
for(let i=0;i<obj.length;i++){
if(obj[i].children.length){//判断是否循环到当前叶子节点
this._forList(obj[i].children,this._setHtml(obj[i],Dom));
}else{
this._setHtml(obj[i],Dom);
}
}
- 获取拖拽对象及目标放置对象
本示例中以ul->li的结构生成目录,理所当然的li是每次拖拽的对象,ul是放置的目标了;
这样就必须在每个li和ul上放上拖拽的事件了;
贴代码:
var liDom1 = document.createElement('li');
liDom1.className = "li"+data.id;
liDom1.draggable = "true";
liDom1.addEventListener('dragstart',function(ev){
ev.dataTransfer.setData("Text", ev.target.className);
_$this.flag = true;
});
...
var ulDom1 = document.createElement('ul');
ulDom1.className = "hide ul"+data.id;
ulDom1.addEventListener('drop',function(ev){
_$this._drop(ev);
})
ulDom1.addEventListener('dragover',function(ev){
_$this._allowDrop(ev);
})
- 注意啦,我要讲重点了,为了在叶子节点后面可以拖拽生成新的节点,那么就必须在叶子节点的li里面添加一个ul;(不好理解吗?就是说当在一个叶子节点的后面拖拽上去一个节点后,这个之前创建的ul就派上用场了,他就会让你想拖拽到其它节点时一样不用再写单独的规则,这也是我快做完了之后才发现的,所以说,写代码啥的麻痹还是的想考虑清楚逻辑啥)
- 最后实现的就是更新数据了
当DOM解构实现了改变那么也需要实时的将原始数据也依据对应的结构进行改变了;
这里想说一句其实如果是使用vue或angular 这些可以进行双向数据绑定的框架,那么这种拖拽的功能就很好完成了,直接获取的改变的数据节点,然后直接变换数据,DOM结构就会重新渲染了,有兴趣的小伙伴做一下吧
插件下载
使用方法:
引用js
<script type="text/javascript" src="https://shangjiahang.github.io/shTest/js/new_file2.js" ></script>
...
<div class="app"></div>
...
<script type="text/javascript">
var arrlist = [];//数据对象
new ztreeObj(arrlist,document.getElementsByClassName("app")[0]);
</script>
文件下载
插件下载