拖动交换各元素位置,并以localStorage存储
#drag-and-drop {
  @include flexbox(row, wrap, space-between, flex-start);
  align-content: flex-start;
  list-style: none;
  padding: 0;
  margin: 0;
  .box {
    width: 32%;
    height: torem(150px);
    border: 1px solid color(black);
    margin-bottom: torem(15px);
    .item {
      @include flexbox(row, nowrap, center, center);
      width: 100%;
      height: 100%;
      color: color(blue);
      font-size: torem(16px);
      user-select: none;
      -webkit-user-drag: element;
      cursor: move;
      &:hover {
        text-decoration: none;
      }
    }
  }
}
import { storage } from 'zp-lib';
const store = storage.proxy('dragAndDrop');
// 默认序列
const LIST = [
  {
    id: 1,
    name: 'one',
  },
  {
    id: 2,
    name: 'two',
  },
  {
    id: 3,
    name: 'three',
  },
  {
    id: 4,
    name: 'four',
  },
  {
    id: 5,
    name: 'five',
  },
  {
    id: 6,
    name: 'six',
  },
  {
    id: 7,
    name: 'seven',
  },
  {
    id: 8,
    name: 'eight',
  },
  {
    id: 9,
    name: 'nine',
  },
];
// drag & drop事件处理
const DragNDrop = {
  /**
   * 开始拖动
   * @param {Object} e - 事件对象
   * @param {Element} e.target - 被拖动的anchor元素
   */
  dragstart: (e) => {
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('from', e.target.dataset.id);
  },
  /**
   * 拖动追踪
   * @param {Object} e - 事件对象
   */
  dragover: (e) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
  },
  /**
   * 释放拖动元素
   * @param {Object} e - 事件对象
   * @param {Element} e.target - 目标anchor元素
   * @param {Element} e.currentTarget - 目标box元素
   */
  drop: (e) => {
    e.preventDefault();
    const frag = document.createDocumentFragment();
    const fromAnchor = document.querySelector(`.item--${e.dataTransfer.getData('from')}`);
    const fromBox = fromAnchor.parentElement;
    // move content
    frag.appendChild(fromAnchor);
    fromBox.appendChild(e.target);
    e.currentTarget.appendChild(frag);
  },
};
/**
 * 绑定事件
 */
function attachEvents() {
  const {
    dragstart,
    dragover,
    drop,
  } = DragNDrop;
  Array.from(document.querySelectorAll('.box')).forEach((item) => {
    item.addEventListener('dragover', dragover, false);
    item.addEventListener('drop', drop, false);
  });
  Array.from(document.querySelectorAll('.item')).forEach((item) => {
    item.onclick = (e) => { e.preventDefault(); };
    item.addEventListener('dragstart', dragstart, false);
  });
}
/**
 * 新建可移动元素
 */
function buildItems() {
  const { data = LIST } = store;
  const frag = document.createDocumentFragment();
  data.forEach(({ id, name }, index) => {
    const box = index + 1;
    const list = document.createElement('li');
    const anchor = document.createElement('a');
    const text = document.createTextNode(name);
    list.classList.add('box', `box--${box}`);
    anchor.classList.add('item', `item--${id}`);
    anchor.setAttribute('draggable', true);
    anchor.setAttribute('href', `#${name}`);
    anchor.dataset.id = id;
    anchor.dataset.name = name;
    anchor.appendChild(text);
    list.appendChild(anchor);
    frag.appendChild(list);
  });
  const target = document.querySelector('#drag-and-drop');
  target.innerHTML = '';
  target.appendChild(frag);
}
document.addEventListener('DOMContentLoaded', () => {
  buildItems();
  attachEvents();
}, false);
window.addEventListener('beforeunload', () => {
  const arr = Array.from(document.querySelectorAll('.item')).map((elem) => {
    const { id, name } = elem.dataset;
    return {
      id,
      name,
    };
  });
  store.data = arr;
}, false);