JS实现简单的拖动编辑器

本篇涉及的知识点有

  1. flex布局,参考阮一峰老师的文章
  2. HTML拖放API
  3. 原生JS控制HTML插入

本篇文章采用H5的拖放API,实现一个简单的控件编辑器,首先用flex布局构建一个简单的左右分栏界面,代码如下

//css
<style type="text/css">
    button{
      padding:5px 20px;
      background: #00a854;
    }
    .container{
      display: flex;
      flex-direction: row;
      align-items: stretch;/*默认值,如果子元素未设置高度或设为auto,将占满整个容器的高度,如果子元素设置高度100%,padding或margin时会导致子元素溢出*/
      height: 600px;
      margin:30px;
    }
    .widget{
      width: 200px;
      margin-right: 10px;
      padding:10px;
      border:1px solid #ccc;
    }
    .zone{
      flex:1 1 auto;
      background: #f1f1f1;
    }
  </style>

//html
<div class="container">
  <div class="widget">
    <button type="button" id="target" draggable="true">drag me</button>
  </div>
  <div class="zone" id="zone">
  </div>
</div>

在H5如果想拖动一个元素非常简单,只需要将它的draggable属性设置true即可,在控件编辑器中,控件自身是一段可插入的HTML,并可以包含css和js脚本

可拖动的元素是控件的外在展示方式,一般用icon展示,此处为了方便,选用button。我们可以在dragstart事件,给拖动的元素用dataTransfer.setData方法设置控件的HTML,然后在拖动结束后添加到Zone,代码具体如下

<script>
  let target=document.getElementById('target');
  let zone=document.getElementById('zone');

  target.ondragstart=function (e) {
      e.dataTransfer.setData('html','<h1>Hello world</h1>');
  };

  zone.ondragover=function (e) {
    e.preventDefault();
    e.dataTransfer.dropEffect='copy';
  };

  zone.ondrop=function (e) {
    e.preventDefault();
    let html=e.dataTransfer.getData('html');
    //插入HTML在DOM Tree的特定位置,不会影响内部已存在的元素,避免额外的序列化,比直接操控innerHTML高效,参考https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
    zone.insertAdjacentHTML('afterbegin',html);
  };
</script>

拖动元素的基本原理就是这样,后续我将展示如何编辑控件

JSBin Demo

推荐阅读更多精彩内容