2015/07/03

Vue.jsだけでページナビゲーション(ページネーション)をつくる

Webサイトなどでページ番号が横一列に並んで、クリックするとそのページ番号に移動するということがしたかった。
最初は、ページ2なら11~20までのレコードを取得して表示するのかと思っていたが、Vue.jsを使うともっと簡単に実装できることがわかった。

ページナビゲーション(ページネーション)の実装方法をまとめる。


追記:2015/07/08
ページ番号付きのページネーションを実装する場合は、下の記事を参考にしてほしい。

追記: 2017/10/26 8:00
当記事のVue.jsのバージョンはv0.12と古いため、新しいバージョンで書き直した。
Vue@2.x+系は、以下の記事を参照してほしい。



ページナビゲーション(ページネーション)をつくる


今回は、簡単に「前へ(prev)」と「次へ(next)」だけのページナビゲーションをつくる。

<!-- index.html -->
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Vue.js De Pagination</title>
    <link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
    <div id="page-demo">
        <div id="pagination">
            <p><a href="#" v-on="click: showPrev" class="{{isStartPage ? 'disabled' : ''}}">prev</a></p>
            <p><a href="#" v-on="click: showNext" class="{{isEndPage ? 'disabled' : ''}}">next</a></p>
        </div>
        <ul>
            <li v-repeat="data: dipsItems">{{data.key}} - {{data.value}}</li>
        </ul>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.1/vue.min.js"></script>
    <script src="index.js"></script>
</body>
</html>
/* style.css */
a.disabled{
    pointer-events: none;
    cursor: default;
    text-decoration: none;
    color: #000000;
}

// index.js
new Vue({
    el: '#page-demo',
    data:{
        page: 0,
        dispItemSize: 3,
        datas: [
            {key: '1', value: 'value1'},
            {key: '2', value: 'value2'},
            {key: '3', value: 'value3'},
            {key: '4', value: 'value4'},
            {key: '5', value: 'value5'},
            {key: '6', value: 'value6'},
            {key: '7', value: 'value7'},
            {key: '8', value: 'value8'},
            {key: '9', value: 'value9'},
            {key: '10', value: 'value10'}
        ]
    },
    methods:{
        showPrev: function() {
            if (this.isStartPage) return;
            this.page--;
        },
        showNext: function() {
            if (this.isEndPage) return;
            this.page++;
        }
    },
    computed:{
        dipsItems: function() {
            var startPage = this.page * this.dispItemSize;
            return this.datas.slice(startPage, startPage + this.dispItemSize);
        },
        isStartPage: function(){
            return (this.page == 0);
        },
        isEndPage: function(){
            return ((this.page + 1) * this.dispItemSize >= this.datas.length);
        }
    }
});


prevをクリックすると、showPrevメソッドが呼ばれ、現在ページをマイナス1する。
このとき、最初のページならキャンセルする。
ついでに、prevリンクを無効化するためにclassに'disabled'を適用させている。

反対に、nextをクリックすると、showNextメソッドが呼ばれ、現在ページをプラス1する。
最後のページならキャンセル、無効化のためにclassに'disabled’を適用。

最初、最後のページの判定は、computedのisStartPage, isEndPageにて行っている。


表示対象になるデータは、computedのdispItemsで設定している。
ここでは、全てが入っているデータ「this.datas」を、現在ページから表示する分だけスライスしてreturnしている。

ちなみに1ページあたりに表示する数は、dispItemSizeに定義されている。




最初は、

v-repeat=”data: datas | limit 現在ページ 表示数”と定義して、filtersでlimit: function(from, to) { this.slice(from, to); }

とか

IndexedDBでIDBKeyRange.bound(from, to, false, false)

みたいに考えていたけど、今回紹介した方法の方が、何十倍も何百倍も簡単だろう。




以上

written by @bc_rikko

0 件のコメント :

コメントを投稿