1. はじめに
最近、Webアプリケーションを作成する仕事が、少しずつですがあります。
その際に使用するのは、殆どの場合「テーブル」です。
素のtableタグを駆使して作成した場合、テーブル内のセルにもう一つテーブルを入れたりとか、自由に設定できるのはいいのですが、表現力が足りなくて、とってもそっけないページになってしまいます。
そこでSPA(Single Page Application)と呼ばれる、表現力のある、インタラクティブに動作するWebページを作成するための方法として、Vue.js(Nuxt.js)や、React.jsがあります。
今回は、Vue.js(Nuxt.js)を使用して、tableを使用したサンプルを作成してみようと思います。
サンプルなので動くのを重視しました。断片的なサンプルはたくさんありますが、断片だと、動作するための必要な所が理解できず、全くの最初から、どう動作させればいいか、分からないことが多いからです。
ここでは以下を使用して、Webアプリケーションのテーブルサンプルを作成したいと思います。
- Vue.js(Nuxt.js)
- Element
- Responder
1.1 Vue.jsとは
Vue.jsとは、以下のようなJavaScript用ライブラリです。
- View のみ
- リアクティブデータバインディング
- HTMLの各タグとデータを自動的に結び付ける
- コンポーネントベース
- 簡単なAPI
お手軽ライブラリのようなので、入門的に導入してみました。
ここでは、Vue.jsを素で扱うのではなく、[Nuxt.js]を使用しようと思います。
1.2 Nuxt.jsとは
Vue.jsは比較的簡単に使用できますが、それでも、なんらかの準備は必要です。
Nuxt.jsとは、その準備を一通りやってくれるフレームワークと思えばいいでしょう。
主な特徴は以下の通りです。
- Vueファイル(*.vue)で記述できる
- サーバーサイドレンダリング
- ES6/ES7 のトランスパイレーション
- モジュール構造で拡張できる
Vue.jsで実装する、vueファイルを追加するだけでいいので、Vue.jsだけを使用するより手軽に実装できます。
1.3 Elementとは
Elementとは、Vue.js 2.0を前提とした、コンポーネントライブラリです。
コンポーネントの種類が多く、しかも制御をVue.jsで記述できるので、便利そうなので使用することにしました。
本稿では、element-uiのコンポーネントとして、el-tableを使用しています。
1.4 Responderとは
Responder とはPython3.6以降で動作する、Webアプリケーションフレームワークです。
今どきのフレームワークはWebSocketなどの非同期をサポートすることが多く、 このフレームワークもその流れで作成されているようです。
今後の勉強として、使えるかと思い、Responder上で作成してみました。
2. 環境
動作させた環境は以下の通りです。
- Ubuntu 18.04
- Python 3.6
- Pipenv 2018.11.26
- node 12.14.0
- npm 6.13.4
- yarn 1.12.3
3. サンプル実装
ここに動作するサンプルを置いておきました。
3.1 サンプルを作成するまでの手順
動作するサンプルは以下のように作成しました。
ひな形作成(npx create-nuxt-app)
以下のようにして、アプリのサンプルを作成します。
$ npx create-nuxt-app
起動すると以下のように尋ねられます。今回は以下のように入力しました。
create-nuxt-app v2.12.0 ? Generating Nuxt.js project in . ? Project name accounts ? Project description accounts project ? Author name Kenichi Tanino ? Choose the package manager Yarn ? Choose UI framework Element ? Choose custom server framework None (Recommended) ? Choose Nuxt.js modules Axios ? Choose linting tools Prettier ? Choose test framework Jest ? Choose rendering mode Single Page App ? Choose development tools jsconfig.json (Recommended for VS Code)
Responder追加
以下で、Responderを準備します。
$ pipenv install responder
run.pyの追加
Responderで実装した、run.pyは以下の通りです。
from pathlib import Path import responder def parentdir(path='.', layer=0): return Path(path).resolve().parents[layer] BASE_DIR = parentdir(__file__, 0) # static_dir => dist api = responder.API(static_dir=str(BASE_DIR.joinpath('dist')), static_route='/') api.add_route("/", static=True) @api.route("/api/accounts") def customer(req, resp): result = { "id": "1", "name": "tanino", "email": "tanino@example.jp", } resp.media = { "status": 200, "result": [result], } if __name__ == '__main__': api.run(address='0.0.0.0')
苦労したところは、ResponderからJavaScriptを返却するように設定するところです。
具体的には、以下のように設定することで、dist/のファイルをResponder経由でアクセスできます。
api = responder.API(static_dir=str(BASE_DIR.joinpath('dist')), static_route='/') api.add_route("/", static=True)
pages/table.vue
pages/table.vueファイルを以下にします。
<template> <el-table :data="accounts"> <el-table-column prop="id" label="id" width="100"> </el-table-column> <el-table-column prop="name" label="Name" width="280"> </el-table-column> <el-table-column prop="email" label="Email" width="280"> <template slot-scope="scope"> <el-input v-model="scope.row.email" ></el-input> </template> </el-table-column> <el-table> </template> <script> import axios from 'axios'; export default { data() { return { accounts: [] } }, async asyncData() { const baseUrl = '/api/accounts' const response = await axios.get(baseUrl) return { accounts: response } } } </script>
上記で難しい所はありませんが、セルの内部にデータを表示するだけでなく、
なんらかの部品を置きたい場合、<template slot-scope="scope">
の中に
el-input的なコントロールを入れると動作します。
データは、”scope.row.email”のように、scope.row内にAPIから返却したデータが入って来るようなので、それらが使用できます。
<el-table-column prop="email" label="Email" width="280"> <template slot-scope="scope"> <el-input v-model="scope.row.email" ></el-input> </template> </el-table-column>
pages/index.vueに以下を追加
table.vueへのリンクをindex.vueに追加しました。
<nuxt-link to="/table">table</nuxt-link>
3.2 動作手順
git clone後、動作させる手順は以下になります。
$ cd practice_the_script/python/responder/ $ yarn install $ yarn run nuxt generate $ pipenv sync $ pipenv run python3 ./run.py
上記をしてから、ブラウザで/tableを見ると以下になります。
4. はまった点
動作しなかった点は以下になります。
API接続できない
なぜかAPI(Python側)にアクセスできない現象が発生しました。
理由は、Axiosのようです。
Nuxt.jsの場合、axiosを使用する方法は、以下があります。
- モジュールとしてインポート
import axios from 'axios';
- nuxtのプラグイン
app.$axios.get ...
モジュールとしてインポートすると、素直に、同一ドメインにアクセスしてくれました。
Nuxt.jsのプラグインとしてaxiosを使用した場合、URLが固定されるようです。
おそらくnuxtのプラグインに設定をする必要があると思います。
5. おわりに
思ったよりは、あっさりと実装出来ました。
ほとんど自分の参考用につくりましたが、誰かの参考になると幸いです。