Vue

by kabanoki

HTML

<script src="//cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
<div id="app">
  <h1>Todos:</h1>
  <table>
    <thead>
      <tr>
        <th>What</th>
        <th></th>
      </tr>
    </thead>
    <tbody v-model="items" is="draggable">
      <tr v-for="(item, idx) in items" :key="idx">
        <td>{{ item.text }}</td>
        <td><span class="handle">⇅</span></td>
      </tr>      
    </tbody>
  </table>  
  <button @click="addRow">Add</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

h1 {
  font-size: 125%;
  font-weight: bold;
  margin-bottom: 1em;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

tr:nth-of-type(2n) {
  background: #f8f8f8;
}

tr:nth-of-type(2n+1) {
  background: #e0e0e0;
}

tr.sortable-ghost {
  opacity: 0;
}

td, th {
  padding: 10px;
}

th {
  font-weight: bold;
  background-color: #666;
  color: #fff
}

.handle {
  cursor: pointer;
}

Vue

new Vue({
  el: "#app",
  data: {
  	items: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }    
    ]
	},
  methods: {
  	addRow() {
    	let item = { text: "Break Table", done: false };
      this.items.push(item);
    }
  }
});