#環境
$ vue --version
2.9.6
#ライブラリの導入と、元のソースコード
今回必要なのは、Nuxt.jsでよくお世話になるUIライブラリVuetifyと、直感的に要素の並び替えができるVue.Draggableを利用させていただきます。
$ 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>
#さあ、並び替えする要素を囲んでみよう(失敗例)
<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>タグ
を囲んで使う。
ただ、これだと要素全体が移動対象になってしまう。。。
<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>タグ
の位置をずらしたり、新たな属性を追加したり、、、、試行錯誤した結果。
この記事より、こんな書き方が。
<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>
カードコンポーネントが、自由に移動できるようになった!!
#追記
サーバーを立ち上げると、こんな警告が。
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
属性にするように」とのこと。
<draggable v-model="posts" tag="v-row">
これだけでおk