data.json

一、基于 ztree 插件实现

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>zTree</title>
  6. <!-- IMPORT CSS -->
  7. <link rel="stylesheet" href="css/reset.min.css">
  8. <link rel="stylesheet" href="css/zTreeStyle.css">
  9. </head>
  10. <body>
  11. <ul class="ztree" id="ztree1"></ul>
  12. <!-- IMPORT JS -->
  13. <script src="js/jquery.min.js"></script>
  14. <script src="js/jquery.ztree.all.min.js"></script>
  15. <script>
  16. // $.fn.zTree.init([容器],[配置项],[数据]);
  17. let $ztree1 = $('#ztree1'),
  18. options = {};
  19. $.ajax({
  20. url: 'data.json',
  21. method: 'GET',
  22. success: result => {
  23. $.fn.zTree.init($ztree1, options, result);
  24. }
  25. })
  26. </script>
  27. </body>
  28. </html>

二、基于 jQuery 的 ztree 插件

  1. ~ function ($) {
  2. function ztree(data) {
  3. let count = 0,
  4. $this = $(this);
  5. // 数据绑定
  6. let bindHTML = function (result) {
  7. let str = ``;
  8. result.forEach(item => {
  9. count++;
  10. let {
  11. name,
  12. open,
  13. children
  14. } = item;
  15. str += `<li>
  16. <a href="" class="title">${name}</a>
  17. ${children?`<em class="icon ${open?'open':''}"></em>
  18. <ul class="level level${count}"
  19. style="display:${open?'block':'none'}">
  20. ${bindHTML(children)}
  21. </ul>`:``}
  22. </li>`;
  23. count--;
  24. });
  25. return str;
  26. };
  27. $this.html(bindHTML(data));
  28. // 基于事件委托实现点击操作
  29. $this.click(function (ev) {
  30. let target = ev.target,
  31. $target = $(target),
  32. $next = $target.next('ul');
  33. if (target.tagName === 'EM') {
  34. $target.toggleClass('open');
  35. $next.stop().slideToggle(100);
  36. }
  37. });
  38. }
  39. $.fn.extend({
  40. ztree: ztree
  41. });
  42. }(jQuery);

三、自己模拟一个ztree

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>zTree树形结构菜单</title>
  6. <!-- import css -->
  7. <link rel="stylesheet" href="css/reset.min.css">
  8. <style>
  9. .container {
  10. box-sizing: border-box;
  11. margin: 20px auto;
  12. padding: 10px;
  13. width: 600px;
  14. border: 1px dashed #AAA;
  15. -webkit-user-select: none;
  16. }
  17. .level {
  18. display: none;
  19. font-size: 14px;
  20. margin-left: 10px;
  21. }
  22. .level.level0 {
  23. display: block;
  24. margin-left: 0;
  25. }
  26. .level li {
  27. position: relative;
  28. padding-left: 15px;
  29. line-height: 30px;
  30. }
  31. .level li .icon {
  32. position: absolute;
  33. left: 0;
  34. top: 9px;
  35. box-sizing: border-box;
  36. width: 12px;
  37. height: 12px;
  38. line-height: 8px;
  39. text-align: center;
  40. border: 1px solid #AAA;
  41. background: #EEE;
  42. cursor: pointer;
  43. }
  44. .level li .icon:after {
  45. display: block;
  46. content: "+";
  47. font-size: 12px;
  48. font-style: normal;
  49. }
  50. .level li .icon.open:after {
  51. content: "-";
  52. }
  53. .level li .title {
  54. color: #000;
  55. }
  56. </style>
  57. </head>
  58. <body>
  59. <div class="container">
  60. <ul class="level level0" id="tree1"></ul>
  61. </div>
  62. <div class="container">
  63. <ul class="level level0" id="tree2"></ul>
  64. </div>
  65. <!-- import js -->
  66. <script src="js/jquery.min.js"></script>
  67. <script src="js/ztree-plugin.js"></script>
  68. <script>
  69. $.ajax({
  70. url: 'data.json',
  71. method: 'get',
  72. success: result => {
  73. $('#tree1').ztree(result);
  74. $('#tree2').ztree(result);
  75. }
  76. });
  77. </script>
  78. <script>
  79. /* let treeModule = (function () {
  80. let $level0 = $('.level0'),
  81. count = 0;
  82. // 获取数据
  83. let queryData = function (callBack) {
  84. $.ajax({
  85. url: 'data.json',
  86. method: 'get',
  87. success: callBack
  88. // success: result => {
  89. // callBack(result);
  90. // }
  91. });
  92. };
  93. // 数据绑定
  94. let bindHTML = function (result) {
  95. let str = ``;
  96. result.forEach(item => {
  97. count++;
  98. let {
  99. name,
  100. open,
  101. children
  102. } = item;
  103. str += `<li>
  104. <a href="" class="title">${name}</a>
  105. ${children?`<em class="icon ${open?'open':''}"></em>
  106. <ul class="level level${count}"
  107. style="display:${open?'block':'none'}">
  108. ${bindHTML(children)}
  109. </ul>`:``}
  110. </li>`;
  111. count--;
  112. });
  113. return str;
  114. };
  115. return {
  116. init() {
  117. // 基于事件委托实现点击操作
  118. $level0.click(function (ev) {
  119. let target = ev.target,
  120. $target = $(target),
  121. $next = $target.next('ul');
  122. if (target.tagName === 'EM') {
  123. // 加减号的切换
  124. $target.toggleClass('open');
  125. // 控制子集的显示隐藏
  126. $next.stop().slideToggle(100);
  127. }
  128. });
  129. queryData(function anonymous(result) {
  130. // 获取数据后完成相关的事项
  131. $level0.html(bindHTML(result));
  132. });
  133. }
  134. }
  135. })();
  136. treeModule.init();
  137. </script>
  138. </body>
  139. </html>

递归数据绑定.png

四、基于原生 js 实现鼠标拖拽

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>DRAG-拖拽</title>
  6. <!-- IMPORT CSS -->
  7. <link rel="stylesheet" href="css/reset.min.css">
  8. <style>
  9. html,
  10. body {
  11. height: 100%;
  12. overflow: hidden;
  13. }
  14. .box {
  15. position: absolute;
  16. top: 0;
  17. left: 0;
  18. width: 100px;
  19. height: 100px;
  20. background: red;
  21. cursor: move;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <div class="box" id="box"></div>
  27. <script>
  28. box.addEventListener('mousedown', down);
  29. function down(ev) {
  30. this.startX = ev.pageX;
  31. this.startY = ev.pageY;
  32. this.startL = this.offsetLeft;
  33. this.startT = this.offsetTop;
  34. // 把执行 BIND 处理后的函数存储到盒子的自定义属性上,绑定的时候绑定存储的这个方法,移除的时候也基于自定义属性获取到这个方法移除
  35. this._MOVE = move.bind(this);
  36. this._UP = up.bind(this);
  37. document.addEventListener('mousemove', this._MOVE);
  38. document.addEventListener('mouseup', this._UP);
  39. }
  40. function move(ev) {
  41. let curL = ev.pageX - this.startX + this.startL,
  42. curT = ev.pageY - this.startY + this.startT;
  43. let minL = 0,
  44. minT = 0,
  45. maxL = document.documentElement.clientWidth - this.offsetWidth,
  46. maxT = document.documentElement.clientHeight - this.offsetHeight;
  47. curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
  48. curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
  49. this.style.left = curL + 'px';
  50. this.style.top = curT + 'px';
  51. }
  52. function up(ev) {
  53. document.removeEventListener('mousemove', this._MOVE);
  54. document.removeEventListener('mouseup', this._UP);
  55. }
  56. </script>
  57. <script>
  58. /* box.onmousedown = down;
  59. function down(ev) {
  60. // 把鼠标起始位置信息和盒子起始位置信息存储到盒子的自定义属性上
  61. this.startX = ev.pageX;
  62. this.startY = ev.pageY;
  63. this.startL = this.offsetLeft;
  64. this.startT = this.offsetTop;
  65. // 按下来在给盒子绑定 MOVE 方法
  66. // 谷歌浏览器中解决鼠标焦点丢失的问题(别绑定给盒子了,绑定给 document),但是要注意 move 中的 this 已经是 document 了,而不是之前的 box,我们需要处理一下
  67. document.onmousemove = move.bind(this);
  68. document.onmouseup = up.bind(this);
  69. }
  70. function move(ev) {
  71. // 随时获取当前鼠标的信息,计算盒子最新的位置
  72. let curL = ev.pageX - this.startX + this.startL,
  73. curT = ev.pageY - this.startY + this.startT;
  74. // 边界判断
  75. let minL = 0,
  76. minT = 0,
  77. maxL = document.documentElement.clientWidth - this.offsetWidth,
  78. maxT = document.documentElement.clientHeight - this.offsetHeight;
  79. curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
  80. curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
  81. this.style.left = curL + 'px';
  82. this.style.top = curT + 'px';
  83. }
  84. function up(ev) {
  85. // 鼠标抬起,把 MOVE 移除掉
  86. document.onmousemove = null;
  87. document.onmouseup = null;
  88. }
  89. */
  90. /*
  91. * // 把鼠标和当前盒子拿绳子捆在一起
  92. this.setCapture();
  93. // 把鼠标和盒子解绑
  94. this.releaseCapture();
  95. 谷歌不支持
  96. */
  97. </script>
  98. </body>
  99. </html>

拖拽.png