【Vue.Draggable】リストやdivタグ以外の要素で、ドラッグアンドドロップで並び替えする方法【Vuetify】

#環境

```shell
$ vue --version
2.9.6
```

#ライブラリの導入と、元のソースコード

今回必要なのは、Nuxt.jsでよくお世話になるUIライブラリ[Vuetify](https://vuetifyjs.com/ja/)と、直感的に要素の並び替えができる[Vue.Draggable](https://github.com/SortableJS/Vue.Draggable)を利用させていただきます。

```shell
$ yarn add @nuxtjs/vuetify
$ yarn add vuedraggable
```

```nuxt.config.js
  buildModules: [
    '@nuxtjs/vuetify',
  ],
```

並び替えしたい要素は、JSONplaceholderから取得した記事情報を落とし込んだカードコンポーネントになります。


```posts/index.vue
<template>
  <v-app dark>
    <v-container>
      <v-row id="main-area">
        <v-col id="feed-template" class="col-4"  v-for="post in posts" :key=post.id>
          <v-card style="overflow:scroll; height:30vh;">
            <v-card-title>
              <nuxt-link :to="'/posts/' + post.id" class="feed-title">{{ post.title }}</nuxt-link>
            </v-card-title>
            <v-card-text class="feed-body">
              <ul class="feed-items">
                <li class="feed-list">
                    {{ post.body }}
                </li>
              </ul>
            </v-card-text>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
import axios from 'axios'
import draggable from 'vuedraggable'

export default {
  components: {
    draggable
  },
  data () {
    return {
      posts: []
    }
  },
  mounted () {
    axios.get('https://jsonplaceholder.typicode.com/posts').then(res => this.posts = res.data)
  }
}
</script>
```

#さあ、並び替えする要素を囲んでみよう（失敗例）

```vue:
<v-app>
  <draggable v-model="posts">
    <v-container>
      <v-row id="main-area">
        <v-col id="feed-template" class="col-4"  v-for="post in posts" :key=post.id>
  // 省略
  </draggable>
</v-app>
```

`v-model`で、配列名を指定した`<draggable>タグ`を囲んで使う。
ただ、これだと要素全体が移動対象になってしまう。。。

```vue:
<v-app>
  <v-container>
    <v-row id="main-area">
      <draggable v-model="posts" draggable=".item">
        <v-col id="feed-template" class="col-4"  v-for="post in posts" :key=post.id>
  // 省略
      </draggable>
    </v-row>
  </v-container>
</v-app>
```

これでもダメ。
`<draggable>タグ`の位置をずらしたり、新たな属性を追加したり、、、、試行錯誤した結果。

>https://mebee.info/2019/12/03/post-4508/

この記事より、こんな書き方が。

```vue
<div id="app">
  <draggable v-model="list" element="ul" :options="{animation:500}">
    <li v-for="item in list" :key="item.id">{{ item.name }}</li>
  </draggable>
</div>
```

ほお！元あったタグ名を`element属性`に設定しておく必要があるんですね！


#カード毎に要素の入れ替えを行う方法（成功例）

つまり、元あったタグを、`<draggable>タグ`で置き換えるイメージで書いていく。
最終的なソースコードはこちら。

```posts/index.vue
<template>
  <v-app dark>
    <v-container>
      <draggable v-model="posts" element="v-row">
        <v-col class="col-4 feed-template" v-for="post in posts" :key=post.id>
          <v-card style="overflow:scroll; height:30vh;">
            <v-card-title>
              <nuxt-link :to="'/posts/' + post.id" class="feed-title">{{ post.title }}</nuxt-link>
            </v-card-title>
            <v-card-text class="feed-body">
              <ul class="feed-items">
                <li class="feed-list">
                  {{ post.body }}
                </li>
              </ul>
            </v-card-text>
          </v-card>
        </v-col>
      </draggable>
    </v-container>
  </v-app>
</template>

<script>
import axios from 'axios'
import draggable from 'vuedraggable'

export default {
  components: {
    draggable
  },
  data () {
    return {
      posts: []
    }
  },
  mounted () {
    axios.get('https://jsonplaceholder.typicode.com/posts').then(res => this.posts = res.data)
  }
}
</script>
```

カードコンポーネントが、自由に移動できるようになった！！


#追記

サーバーを立ち上げると、こんな警告が。

```shell
 WARN  Element props is deprecated please use tag props instead. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#element-props
```

どうやら「`element`は廃止されるので、`tag`属性にするように」とのこと。

```vue
      <draggable v-model="posts" tag="v-row">
```

これだけでおｋ