element ui のtableにinfinite scroll を付けてみた
はじめに
nuxt.jsでelement uiを使用したテーブルコンポーネントに下記のようなinfinite scrollを実装してみました。
今回使用したライブラリはvue-infinite-loadingを利用しました。
環境構築編
$ create-nuxt-app <project-name> $ cd <project-name> $ npm install $ npm install --save vue-infinite-loading element-ui
element uiのコンポーネントを使用できるようにします。
plugins/element-ui.js
import Vue from 'vue' import 'element-ui/lib/theme-chalk/index.css' const ElementUI = require('element-ui') Vue.use(ElementUI)
nuxt.config.js
export default { ... plugins: [ { src: '~/plugins/element-ui' } ], ... }
pageの実装
次にpageを実装していきます。
pages/index.vue
<template> <section> <el-button @click="resetInfinite">reset</el-button> <div class="table-container"> <el-table :data="accounts" style="with: 100%"> <el-table-column prop="id" label="id" /> <el-table-column prop="name" label="name" /> <el-table-column prop="email" label="email" width="180" /> </el-table> </div> </section> </template> <script> export default { data() { return { accounts: [] } }, created() { for (let i = 0; i < 300; i++) { var account = { id: i + 1, name: `test_${i + 1}`, email: `test_${i + 1}@example.com` } this.accounts.push(account) } } } </script>
いよいよinfinite scrollを実装していきます。
まずはvue-infinite-loadingをimportします。
pages/index.vue
<script> import InfiniteLoading from 'vue-infinite-loading' export default { components: { InfinitLoading }, ... </script>
テーブルのはみ出した要素はscrollするようにしましょう。
pages/index.vue
<style> .table-container > .el-table > ..el-table__body-wrapper { overflow: scroll; max-height: 480px; } </style>
InfiniteLoadingのコンポーネントをel-tableの一番下に追加します。 さらにテーブルで使用するデータをaccountsから変更します。
pages/index.vue
... <div class="table-container"> <el-table :data="list" style="with: 100%"> <el-table-column prop="id" label="id" /> <el-table-column prop="name" label="name" /> <el-table-column prop="email" label="email" width="180" /> <InfiniteLoading slot="append" :identifier="infiniteId" force-use-in-infinite-wrapper=".el-table__body-wrapper" @infinite="infiniteHandler" /> </el-table> </div> ... <script> ... data () { return { accounts: [], list: [] } } } </script>
スクロールされたら走るinfiniteHandlerを実装しましょう。
... data() { return { accounts: [], list: [], limit: 15, page: 0, infiniteId: +new Date() } }, created() { for (let i = 0; i < 300; i++) { var account = { id: i + 1, name: `test_${i + 1}`, email: `test_${i + 1}@example.com` } this.accounts.push(account) } this.fetchList(this.limit) }, methods: { infiniteHandler($state) { if (this.accounts.length && this.accounts.length > this.list.length) { let scrollLimit = (this.page + 1) * this.limit if (this.accounts.length < scrollLimit) { scrollLimit = this.accounts.length } this.fetchList(scrollLimit) $state.loaded() } else { $state.complete() } }, fetchList(scrollLimit) { this.list.push( ...this.accounts.slice(this.page * this.limit, scrollLimit) ) this.page++ }, resetInfinite() { this.page = 0 this.list = [] this.fetchList(this.limit) this.infiniteId++ const elm = document.getElementsByClassName('el-table__body-wrapper')[0] elm.scrollTo({ top: 0 }) } } }
if (this.accounts.length && this.accounts.length > this.list.length) {}
で現在表示されているデータよりもaccountsが多ければinfinite scrollでデータが読み込まれるようになっています。
scrollLimitには何件目までのデータを取得するかが入り、
this.list.push( ...this.accounts.slice(this.page * this.limit, scrollLimit) )
で現在読み込まれているデータ+1番目のデータからscrollLimitまでのデータをlistに追加します。