Vue.js + @shopify/draggable에서 SortTable

소개



Vue.js와 @shopify/draggable을 사용하여 SortTable을 시도했습니다.

draggable.vue


<script>
import { Sortable } from '@shopify/draggable';

const removeElement = function(node) {
  return node.parentElement.removeChild(node);
};

const insertElement = function(fatherNode, node, position) {
  const refNode = (position === 0) ? fatherNode.children[position] : fatherNode.children[position - 1].nextSibling;
  fatherNode.insertBefore(node, refNode);
};

export default {
  props: {
    value: {
      required: true,
      type: Array,
    },
    element: {
      required: false,
      type: String,
      default: 'div',
    },
    draggableOptions: {
      required: false,
      type: Object,
      default: () => ({}),
    },
  },

  mounted() {
    const draggable = new Sortable(this.$el, this.draggableOptions);
    this.$once('hook:beforeDestroy', () => {
      draggable.destroy();
    });

    draggable.on('sortable:start', e => {
      this.$emit('start', e);
    });

    draggable.on('sortable:sort', e => {
      this.$emit('sort', e);
    });

    draggable.on('sortable:sorted', e => {
      this.$emit('sorted', e);
    });

    draggable.on('sortable:stop', e => {
      if (e.oldIndex !== e.newIndex) {
        const item = removeElement(e.dragEvent.source);
        insertElement(e.dragEvent.sourceContainer, item, e.oldIndex);
        this.spliceList([...this.value], e.oldIndex, e.newIndex);
      }
      this.$emit('stop', e);
    });
  },

  methods: {
    spliceList(list, oldIndex, newIndex) {
      const item = list.splice(oldIndex, 1)[0];
      list.splice(newIndex, 0, item);
      this.$emit('input', list);
      this.$emit('change', { item, oldIndex, newIndex });
    },
  },

  render(h) {
    return h(this.element, { attrs: this.$attrs }, this.$slots.default);
  },
};
</script>

app.vue


<template>
  <div id="app">
    <Draggable
      v-model="list"
      element="ul">
      <li
        v-for="(row, index) in list"
        :key="row.id || `key${index}`"
        class="draggable-source">
        {{ row.text }}
      </li>
    </Draggable>
  </div>
</template>

<script>
import Draggable from './draggable.vue'

export default {
  name: 'app',

  data: () => ({
    list: [
      { id: 1, text: 'テスト1' },
      { id: 2, text: 'テスト2' },
      { id: 3, text: 'テスト3' },
      { id: 4, text: 'テスト4' },
      { id: 5, text: 'テスト5' },
    ],
  }),

  components: {
    Draggable,
  },
}
</script>
sortable:stop 이벤트로 소트 된 DOM를 되돌리고, Vue data
자신을 정렬하고 있습니다.

결과



좋은 웹페이지 즐겨찾기