树形操作2-或、且关系组合

  demo 预览
  
  github 源代码
  
  实现功能点:
  
  tab 切换展示树数据
  
  树形展示、筛选
  
  左侧节点支持拖拽到右侧,并且可组合为或、且的关系
  
  右侧节点支持删除,并统计节点个数
  
  支持默认数据回填
  
  模拟获取保存数据
  
  截图:
  
  具体实现-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">已重组节点(www.michenggw.com<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"www.fengshen157.com>' + 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'www.fenghuang1999.com), 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(www.haitianguo.cn ).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 源代码。
  
  最后就是,目前实现的方案,只支持二级树结构,多级是不支持的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值