树形操作2-或、且关系组合
树形操作数据整理总结,这篇是第二篇。本篇是关于树节点拖拽组合,实现或、且的关系,并支持删除节点。demo 是基于 jquery 及 easy-ui 库实现的。
截图:
具体实现-loading:
利用 css3 实现。主要运用了 :before
,:after
选择器‘画’了两个圆点,最后利用animation
及transform:translateX() scale()
实现动画。利用位移模拟的旋转,为了使效果更好,加了一点点缩放。
html:
<div class="loading"></div>
css:
.loading { position: relative; height: 100%; line-height: 100%; }.loading:before,.loading:after { position: absolute; top: calc(50% - 5px); left: calc(50% - 5px); content: ""; width: 10px; height: 10px; border-radius: 100%; }.loading:before { background: skyblue; animation: loading-reverse .8s linear infinite; }.loading:after { background: yellow; animation: loading .8s linear infinite; } @keyframes loading { from { transform: translate(-20px) scale(.8); } to { transform: translate(20px) scale(1.1); } } @keyframes loading-reverse { from { transform: translate(20px) scale(.8); } to { transform: translate(-20px) scale(1.1); } }
本想用一个 loading + reverse 实现,但实现效果不是很理想,就用了两个。下面是一个 loading 的代码,可以试一下。
.loading:before { background: skyblue; animation: loading .8s linear infinite reverse; }.loading:after { background: yellow; animation: loading .8s linear infinite; } @keyframes loading { from { transform: translate(-20px) scale(.8); } to { transform: translate(20px) scale(1.1); } }
具体实现:
html 结构比较简单,左右布局;左边是外加了一个 tab 切换及筛选。右侧,默认一个清空按钮。结构如下:
<div class="tree-drag-relation"> <div class="left"> <ul class="nav loading" id="nav"></ul> <div class="search tree-header" id="search"> <input class="search-input" placeholder="搜索标签" value="" /> </div> <ul class="tree-con loading" id="tree_drag"></ul> </div> <div class='right'> <div class="relation-header"> <span class="tip-num">已重组节点(<span class="num" id="node_num">0</span>)</span> <span class="clear-all" id="clear_all">清空</span> </div> <div class="relation-con and-wrap" id="relation_con"> </div> </div></div>
为了使 js 代码逻辑清晰,结构组织分为了左右 2 部分。左侧,负责 tab 切换及树形数据的展示等,结构如下:
右侧负责 或、且 逻辑的处理、删除、展示及回填等,结构如下:
tab 切换
tab 切换比较简单,就不上代码了。
树形展示
数据树形展示,利用的是 easyui 插件的 tree 插件,按照官方 API,很容易就能实现。
关键点一:要求数据格式为:
[{ id: '', text: '', children: [{}] // 依次类推 }]
关键点二:设置支持拖拽,且在加载成功后,设置当前树节点不可放置被拖拽的节点。具体可看renderDragTree
这个方法。
treeDragMod.$treeTarget.tree({ data: treeData, dnd: true, // 允许拖拽 formatter: function(node) { // 统计子节点个数 var text = '<span class="node-name">' + node.text + '</span>'; if (node.children && node.children.length > 0) { text += '<i class="tip">(' + node.children.length + ')</i>'; } return text; }, onLoadSuccess: function(e, node) { // 折叠树 treeDragMod.$treeTarget.tree('collapseAll'); // 节点上禁止放置 $.each($('#tree_drag .tree-node'), function(i, item) { $(item).droppable("disable"); }); } }); relationMod.setDragAndDrop();
关键点三:放置,或且的渲染。拖拽实现的另一个点就是放置,因此另一个关键点就是设置放置点,并进行放置逻辑处理,这是实现 或、且 关系的重点。具体可看setDragAndDrop
方法实现。
//设置被拖元素$("#tree_drag .tree-node").draggable({ proxy: 'clone', revert: true, //拖动结束后节点将返回它的开始位置 cursor: 'pointer', onStartDrag: function () { $(this).draggable('proxy').css({'background': '#fff', 'opacity': '0.5'}); }, onStopDrag: function (e) { var $target = $(e.target), node = $('#tree_drag').tree('getNode', e.data.target), // 获取被拖动的节点 $clearAll = $('#clear_all'); // 判断在可拖拽放置区域,才进行放置操作 if ($target.hasClass('and-wrap') || $target.hasClass('or-wrap')) { $clearAll.show(); $target.append(conHtml()); } function conHtml (relation) { // 处理 and 且的关系 var conHtml = ''; if ($target.hasClass('and-wrap')) { if ($target.children().length) { conHtml += relationMod.andHtml; } var innerHtml = node.children ? relationMod.orConHtml(node.children) : relationMod.orItemHtml(node); conHtml += relationMod.orWrapLeftHtml + innerHtml + '</div>'; } else if ($target.hasClass('or-wrap')) { // 处理 or 或的关系 if ($target.children().length) { conHtml += relationMod.orHtml; } conHtml += node.children ? relationMod.orConHtml(node.children) : relationMod.orItemHtml(node); } return conHtml; } relationMod.setNodeNum(); relationMod.resizeScrollTop(); } });// 设置目标对象允许放置被拖元素$(".and-con, .or-con").droppable();
或、且关系添加时,是通过判断当前添加节点的元素是否有子元素,有那么添加元素的时候,就需要添加对应的关系。考虑,添加元素没有子节点时,是只需添加节点,而不需要添加关系。
关键点四:节点删除。
假如箭头为或且
,第一次删除A
或B
或C
都正确。
采用删除字母的同时,判断,上一个箭头存在,则需要删除上一个,否则需要删除下一个箭头。
删除 或 item 的如下:
$('body').on('click', '.item-del', function () { // 删除 item var $this = $(this), $item = $this.closest('.item'), $orWrap = $this.closest('.or-wrap'); // 删除当前元素及关系 // 上一个存在,删上一个,否则删下一个 var $prev = $item.prev('.or'); if ($prev.length) { $prev.remove(); } else { var $next = $item.next('.or'); if ($next.length) { $next.remove(); } } $item.remove(); // 删除后,若其父元素无子元素,则删除其父元素 if ($orWrap.children('.item').length == 0) { $orWrap.remove(); } relationMod.setNodeNum(); })
删除且的逻辑和这个类似。
其他操作比较简单,就不赘述了,具体实现可看github 源代码。
最后就是,目前实现的方案,只支持二级树结构,多级是不支持的。
原文出处:https://www.cnblogs.com/EnSnail/p/10268643.html
作者:ESnail
共同学习,写下你的评论
评论加载中...
作者其他优质文章