ということで、シンプルな構成でソート可能なテーブルをVue.jsをつかってつくる。
vueのバージョンは2系(2.5で動作確認)を使う。
ソート可能なテーブルをつくる
<main id="app">
<table>
<thead>
<tr>
<th
:class="sortedClass('id')"
@click="sortBy('id')"
>
ID
</th>
<th
:class="sortedClass('name')"
@click="sortBy('name')"
>
Name
</th>
<th
:class="sortedClass('age')"
@click="sortBy('age')"
>
Age
</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in sortedItems"
:key="item.id"
>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</tbody>
</table>
</main>
// import vue@2.5
new Vue({
el: '#app',
data () {
return {
sort: {
key: '',
isAsc: false
},
items: [
{ id: 1, name: 'taro', age: 20 },
{ id: 2, name: 'jiro', age: 15 },
{ id: 3, name: 'saburo', age: 18 },
{ id: 4, name: 'shiro', age: 14 },
]
}
},
computed: {
sortedItems () {
const list = this.items.slice(); // ソート時でdataの順序を書き換えないため
if (!!this.sort.key) {
list.sort((a, b) => {
a = a[this.sort.key]
b = b[this.sort.key]
return (a === b ? 0 : a > b ? 1 : -1) * (this.sort.isAsc ? 1 : -1)
});
}
return list;
}
},
methods: {
sortedClass (key) {
return this.sort.key === key ? `sorted ${this.sort.isAsc ? 'asc' : 'desc' }` : '';
},
sortBy (key) {
this.sort.isAsc = this.sort.key === key ? !this.sort.isAsc : false;
this.sort.key = key;
}
}
});
table {
th {
cursor: pointer;
&.sorted {
&.asc::after {
display: inline-block;
content: '▼';
}
&.desc::after {
display: inline-block;
content: '▲';
}
}
}
}
th要素にクリックイベントを登録し、sortBy(key)
でソートするキーと順番を設定する。すると
computed#sortedItems
が再計算され、データがソートされるという仕組み。Array.prototype.sort
はミュータブルなメソッドなので、もとのdata#items
の並び順を変えないためArray.prototype.slice
で配列をコピーしてからソートしている。普段
Array.sort((a, b) => a - b)
のように実装すると思うのだが、その結果に昇順なら*1
、降順なら*-1
をして並び順をかえている。methods#sertedClass
は、ソートされているラベルに▲/▼を表示するために使っている。ラベルがクリックされたら
th.sorted.asc
やth.sorted.desc
のようにclassを設定し、疑似要素::afterで▲/▼を表示している。今回紹介したソート可能なテーブルを、より汎用的なコンポーネントにする場合はちょっと手間がかかるのでUIライブラリなどの利用を検討されたほうが良いだろう。
(もしくはElementUIを参考にするとか)
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿