スクリプトのお勉強

Nuxt.js + Element + Responderでのtableサンプル作成

投稿日:

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. おわりに

思ったよりは、あっさりと実装出来ました。
ほとんど自分の参考用につくりましたが、誰かの参考になると幸いです。

-スクリプトのお勉強

執筆者:

関連記事

ワンライナーから使いそうなのを抜粋

ワンライナー多すぎ、、 https://linuxcommandlibrary.com/basic/oneliners は膨大なワンライナーがあっていいのですが、多すぎて、何が使えるかぱっと見分かりま …

顔画像のモザイク方法(python + OpenCV + face_recognition)

Python3での顔画像モザイク方法 python3での顔画像モザイクの方法を調べてみました。 仕事とは関係なく、単なる趣味だったりしますが。。 この内容で、Djangoと統合する予定です。 Open …

CentOS7をRocky Linux 9に移行する

このVMのOSをCentOS7にした関係上、そろそろupdateする必要があります。そもそもCentOS7を選択した理由は、仕事で使用するからでした。 で、仕事ではRocky Linux 9なので、こ …

Python3/ある日付から日付までの月/日/時間ごとの時刻を算出する

小ネタです。 要するに、時刻A と 時刻B を指定したときの、各時間間隔での時刻取得したかったです。 当初はdateutilを使う方法でなく、自前で実装しようと思ったのですが、面倒なことに気づきました …

神奈川県横浜市神奈川区のワクチン接種地図作った

作ってみた。東白楽駅を真ん中にしてみました。なんとなく真ん中な感じなので。 データ元 以下のテキストデータからゴニョゴニョしてます。 https://www.city.yokohama.lg.jp/k …

google オプトアウト Click here to opt-out.