もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

element-uiのdialog使ってみた

はじめに

UIフレームワークelement-ui使ってみました。

今までbootstrapばっかりだったので、ちょっと覚えるの大変だなーと思ってたんですが、そこまで大変じゃなかったです。

表題のdialogはbootstrapでいうmodalですが、こちらも簡単でした。

ただ、nuxtを使用しつつ使う場合に、親コンポーネントとdialog用のコンポーネントと連携でハマっちゃった(初心者だからですが・・・)ので忘れないように記載しときます。

やってみた

TestMain.vue

<template>
  <div>
    <test-list v-on:onModal="onModal(true)" />
    <test-modal
      v-bind:dialogTableVisible="dialogTableVisible"
      v-on:onModal="onModal(false)"
    />
  </div>
</template>

<script>
import TestList from '~/components/test/TestList.vue'
import TestModal from '~/components/test/TestModal.vue'

export default {
  layout: 'default',
  components: {
    TestList,
    TestModal
  },
  data: function() {
    return {
      dialogTableVisible: false
    }
  },
  methods: {
    onModal: function(dialogTableVisible) {
      this.dialogTableVisible = dialogTableVisible
    }
  }
}
</script>

TestList.vue

このvueは例えば、管理画面のデータリストを想定したコンポーネントです。

実際はel-tableでデータのリストを表示して、それぞれのレコードに編集などのボタンが付き、それをdialogで表示するようなイメージです。

<template>
  <el-row class="test-list-field">
    <el-col :span="24">
      <el-card class="box-card">
        <el-button type="primary" @click="showModal">モーダル表示</el-button>
      </el-card>
    </el-col>
  </el-row>
</template>

<script>
export default {
  methods: {
    showModal() {
      this.$emit('onModal')
    }
  }
}
</script>

TestModal.vue

<template>
  <el-dialog
    title="テストモーダル"
    :visible.sync="$props.dialogTableVisible"
    :before-close="hideModal"
  >
    <span slot="footer" class="dialog-footer">
      <el-button type="info" @click="hideModal">モーダル閉じる</el-button>
    </span>
  </el-dialog>
</template>

<script>
export default {
  props: {
    dialogTableVisible: {
      type: Boolean
    }
  },
  methods: {
    hideModal() {
      this.$emit('onModal')
    }
  }
}
</script>

f:id:kojirooooocks:20181204031037g:plain

結果、自分の以前の記事で使っていた、親 ⇔ 子の通信部分で使用した方法で行けました。

  1. propsで、dialogのopen/closeを取り扱うデータを送る
  2. v-onで親のonModal()をlistenする
  3. el-dialogの :before-close で$emitを実行するメソッドを設定する
  4. クリック時に$emitで子から、カスタムイベントを発火させる

重要なのは3で、これを設定しとかないと、$propsのデータを編集使用してしまうようで、以下のエラーになっちゃいました。

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "dialogTableVisible"

終わりに

かんたんな話でしたが、とりあえずこのような感じでした。

現場からは以上です。

nuxtでsweetalert使ってみた

はじめに

めちゃめちゃ簡単な記事ですが、残しとかないと忘れるので書いときます。

現在のプロジェクトではsweetalertを使ってます。

アラートなどリッチに表示できるので重宝してます。

新たなプロジェクトではnuxtを使うようになったのですが、こちらでも使い続けたいなと思ってたので、調べてみるとvue-sweetalert2というのがあったので、導入しました。

やってみた

インストール

$ yarn add vue-sweetalert2

nuxt.config.jsに記入

/*
** Nuxt.js modules
*/
modules: [
  'vue-sweetalert2/nuxt'
],

使い方

methodsなどで使用する場合以下

this.$swal('テストアラート')

ちょこっと複雑なのとかは以下

this.$swal({
  title: 'データの削除確認',
  text: '本当に削除しますか?',
  type: 'warning',
  showCancelButton: true,
  confirmButtonClass: 'btn btn-danger',
  cancelButtonClass: 'btn btn-info',
  confirmButtonText: '削除する',
  cancelButtonText: 'キャンセル',
  reverseButtons: true,
  buttonsStyling: false
}).then(result => {
  if (result.value) {
    // 削除処理
  }
})

終わりに

めちゃめちゃ簡単に実装できました。

Reactでも似たようなsweetalert2-reactというのがあったのですが、nuxtのほうが簡単な印象でした。

ここまで進めたのですが、element-uiのmessageBoxの存在を知ってからは、そっちでもいんじゃね?と思うようにもなりました。

アドベントカレンダーの振り返り

メリークリスマス

日付は12/25となり、アドベントカレンダー終了日になりました。

今回初となるアドベントカレンダー参加は以下のようになりました。

真・エンジニアの登壇を応援する会 Advent Calendar 2018

adventar.org

f:id:kojirooooocks:20181225201634p:plain

kojirooooocks.hatenablog.com



write-blog-every-week Advent Calendar 2018

adventar.org

f:id:kojirooooocks:20181225201646p:plain

kojirooooocks.hatenablog.com



Symfony Advent Calendar 2018

qiita.com

f:id:kojirooooocks:20181225201812p:plain

kojirooooocks.hatenablog.com



Kojirockの1人アドベントカレンダー Advent Calendar 2018

adventar.org

f:id:kojirooooocks:20181225202021p:plain




といった感じで、一人アドベントカレンダーが未達となりました。

他のアドベントカレンダーは、他の人達に迷惑をかけないために、プライオリティ高くしていたので達成できましたが、上記の通り一人アドベントカレンダーはボロボロでした。

未達の原因は大まかに以下です。

  1. 12月中に長期の体調不良に陥った
  2. クリスマス付近は家族との時間を作るための時間を作った
  3. 忘年会シーズンだった
  4. はてなの予約投稿機能を11月末に知った

想定不足が続いたといえば言い訳になりますが、他の人達は無事書き終えているので、単純に甘さが招いた失敗です。

今年の失敗を活かし、来年も一人アドベントカレンダーを実践して、次こそは完走したいとおもいます。

実際子供や家族との時間を考えると、一人の勉強期間は少し限られるのは事実なので、それを踏まえて考えるとやはり書き溜めが重要だなと感じました。

なので来年は、10月くらいからちょこちょこ書き溜めておこうとおもいます。




また、来年は一人アドベントカレンダー完走以外にもいろいろと目標があるので、それらの目標も達成しつつ、完走を目指したいです。

ちなみに来年の目標は、こちらです。

本日時点では、もう少し明確になり、かつ、数も増えているので、来年初日のブログで発表しようかなと思っています。

終わりに

ふとgmailの受信リストを見ると、

「1年前のブログ「続ける技術」などを振り返りませんか?」

というメールがはてなから届いてました。

ちなみに以下のブログです。

kojirooooocks.hatenablog.com

昨年のブログ数から考えたら、たしかにブログに関しては(数的に)がんばれたと思っています。

来年は、更に目標を高く持って頑張りたいと思います!

Symfony4でNelmioApiDocBundleを試してみた

はじめに

こんばんは。 この記事はSymfony Advent Calendar 2018 20日目の記事です。

よろしくおねがいします。

現在僕は、CakePHP+Nuxtを使用して、webアプリケーションのフルリプレイス作業を行っています。

バックエンドのフレームワークは、人数や時間、スキル的な縛りがあり、既存で使用しているCakePHPのままになりました。

フロントはNuxtを採用しており、バックエンドの役割はapiやshellのみになっています。

そのため、APIドキュメントをきちんと作成するためSwaggerを採用しています。

CakePHPでは良さげなパッケージがあったのですが、@polidogさんからSymfony Advent Calendar の話を聞いて、ふと、Symfonyだとどうやるのかな?と思って、やってみました。

ちなみに自分のSymfony歴は、1系を1.5年程度、2系(2.2とかだった気がする)を1年程度で、それ以降は完全に離れていて、完全に浦島太郎です。

やってみた

packagistで調べてみると、以下あたりが該当しそうでした。

その後、Symfony自体の操作を思い出すために公式を流し見していたのですが、NelmioApiDocBundleの紹介があり、Swaggerの記載があったので、使えるのかな?と思い、こちらにしました。

と、いうより、まず最新のsymfonyを全く触ってないので、そこからでした。

なので、インストールからやります。

インストール

$ composer create-project symfony/website-skeleton test-swagger

実行してみる

$ php bin/console server:start                                                                     
 [OK] Server listening on http://127.0.0.1:8000

f:id:kojirooooocks:20181205025517p:plain

入りました。

次は、公式のインストール手順を確認しながらNelmioApiDocBundleをインストールしてみます。

ライブラリインストール

$ composer require nelmio/api-doc-bundle
$ php bin/console assets:install 

次はAppKernel.phpにインストールしたパッケージをnewするところです。

f:id:kojirooooocks:20181205025535p:plain

ただ、AppKernel.phpが存在しない。。。

自分で作るのかどうするのか調べてたんですが、↓を見る感じ、config/bundles.phpに追加するようです。

バージョンが上がってからの変更だと思います。

f:id:kojirooooocks:20181205025551p:plain

次に、ドキュメントを表示するためのroutingを登録します。

ここは公式通りでいけました。

config/routes.yaml
app.swagger_ui:
    path: /api/doc
    methods: GET
    defaults: { _controller: nelmio_api_doc.controller.swagger_ui }

app.swagger:
    path: /api/doc.json
    methods: GET
    defaults: { _controller: nelmio_api_doc.controller.swagger }

公式では次に、config/config.ymlに設定ファイルを登録するようですが、config.ymlが存在しませんでした。

調べてみると、以下を見かけました。

https://stackoverflow.com/questions/49799385/symfony4-app-config-config-yml-is-missing

config/packages/***.yaml として登録するようです。

こちらもバージョンが上がってからの変更だと思います。

なので、nelmio_api_doc.yamlとして配置します。

内容はほぼ公式のままです。

nelmio_api_doc:
  documentation:
    host: 127.0.0.1:8000
    schemes: [http]
    info:
      title: My App
      description: This is an awesome app!
      version: 1.0.0
  areas:
    path_patterns: [ ^/api(?!/(doc|doc.json)$) ]

f:id:kojirooooocks:20181205025611p:plain

f:id:kojirooooocks:20181205025621p:plain

とりあえずローカルで表示できました。

実際にAPI追加してみます。

指定されたAnnotationで登録していきます。

SymfonyのRoute Annotationを書くと、APIのパスとmethodを、Swaggerの形式によしなに解釈してくれるようです。

<?php
/**
 * Created by PhpStorm.
 * User: yudai_fujita
 * Date: 2018-12-05
 * Time: 01:21
 */

namespace App\Controller;

use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;

class HelloController
{
    /**
     * @Route("/api/hello/{name}/", methods={"GET"})
     * @SWG\Parameter(
     *     name="name",
     *     in="path",
     *     description="挨拶したい名前",
     *     type="string"
     * )
     * @SWG\Response(
     *     response=200,
     *     description="挨拶するよ",
     *     @SWG\Schema(
     *         type="string"
     *     )
     * )
     * @SWG\Tag(name="hello")
     */
    public function hello(string $name = '')
    {
        return JsonResponse::fromJsonString("hello {$name}");
    }
}

f:id:kojirooooocks:20181205025638p:plain

f:id:kojirooooocks:20181205025654p:plain

表示されました。

/api/doc.jsonにアクセスすると、今回作成したデータが含まれたjsonが表示されます。

f:id:kojirooooocks:20181205025724p:plain

本当にswaggerが食ってくれるか、swagger editorで確認してみます。

本来は、ci回して、そのときに開発サーバーとかに、api/doc.jsonが展開される感じかと思いますが、今回はローカルなので、jsonファイルにしてアップします。

$ wget http://127.0.0.1:8000/api/doc.json

f:id:kojirooooocks:20181205025739p:plain

表示されました。

終わりに

最新のSymfonyの動きについていけてなかったので、無駄にはまってしましましたが、記事書きながら2~3時間程度でなんとかなりました。

そして久しぶりにSymfonyに触ったのですが、Symfony2の頃よりディレクトリ構造など、わかりやすくなっている印象を受けました。

また触り始めたいです。

簡単でしたが、現場からは以上です。

Nuxt.jsビギナーズガイドを読んだ Vol.2

はじめに

こんにちは。

Kojirockの1人アドベントカレンダー Advent Calendar 2018の19日目の記事です。

プライベートが忙しくて、最近は日付が変わってからのアップがデフォルトです。

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

今回は、2章、3章のはじめあたりを中心に勉強しました。

やってみた

1. 以前のソースのリクエスト部分をvuexへ移す

本書で紹介されている、vuxeストアのクラシックモードを使用して、以前の天気予報取得ロジックをstoreに移動します。

store/index.js
import Vuex from 'vuex'

export default () =>
  new Vuex.Store({
    state: {
      weatherData: ''
    },

    getters: {
      weatherData: state => state.weatherData
    },

    mutations: {
      setWeatherData(state, weatherData) {
        state.weatherData = weatherData
      }
    },

    actions: {
      async fetchWeatherData({ commit }, { pref }) {
        const url = `https://api.openweathermap.org/data/2.5/weather?q=${pref}&APPID=${
          process.env.OPENWEATHERMAP_API_KEY
        }`
        const response = await this.$axios.$get(url)
        commit('setWeatherData', response.weather[0].main)
      }
    }
  })
pages/weather/_pref.js
<template>
  <div>
    <p>只今の{{ prefName }}の天気</p>
    <span>{{ weatherName }}です</span>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  data() {
    return {
      weatherTypeList: {
        Clouds: '曇り',
        Rain: '雨',
        Snow: '雪',
        Clear: '晴れ'
      },
      availablePrefList: {
        aomori: '青森',
        saitama: '埼玉',
        osaka: '大阪',
        hiroshima: '広島',
        okinawa: '沖縄'
      }
    }
  },
  validate({ params }) {
    return (
      ['aomori', 'saitama', 'osaka', 'hiroshima', 'okinawa'].indexOf(
        params.pref
      ) !== -1
    )
  },

  async fetch({ store, params }) {
    try {
      await store.dispatch('fetchWeatherData', { pref: params.pref })
    } catch (e) {
      console.log(e)
    }
  },

  computed: {
    weatherName: function() {
      return this.weatherTypeList[this.weatherData]
    },
    prefName: function() {
      return this.availablePrefList[this.$route.params.pref]
    },
    ...mapGetters(['weatherData'])
  }
}
</script>

f:id:kojirooooocks:20181220015422p:plain

Vue Dev Toolでstoreの情報も確認できるのですが、きちんとデータが入っていました。

2. Layoutを切り替える

デフォルトのlayoutを使わずに、別途新しいLayoutファイルを作ってそれを適用してみます。

今回は、UI フレームワークの Element UIのヘッダー・フッダー・サイドバーを表示するようなlayoutを作成してみます。

使用しているのは、Element UIの公式に乗っているものとほぼほぼ一緒です。

components/KrHeader.vue
<template>
  <el-header>
    Kojirock Header
  </el-header>
</template>

<style>
.el-header {
  background-color: #b3c0d1;
  color: #333;
  text-align: center;
  line-height: 60px;
}
</style>
components/KrFooter.vue
<template>
  <el-footer>
    Kojirock Footer
  </el-footer>
</template>

<style>
.el-footer {
  background-color: #b3c0d1;
  color: #333;
  text-align: center;
  line-height: 60px;
  margin-top: auto;
}
</style>
components/KrSideMenu.vue
<template>
  <el-aside width="200px">
    Side Menu
  </el-aside>
</template>

<style>
.el-aside {
  background-color: #d3dce6;
  color: #333;
  text-align: center;
  line-height: 200px;
}
</style>
layouts/kojirock.vue
<template>
  <el-container>
    <el-container>
      <k-r-side-menu />
      <el-container id="kr-main">
        <k-r-header />
        <el-main><nuxt/></el-main>
        <k-r-footer />
      </el-container>
    </el-container>
  </el-container>
</template>

<script>
import KRHeader from '~/components/KRHeader.vue'
import KRFooter from '~/components/KRFooter.vue'
import KRSideMenu from '~/components/KRSideMenu.vue'
export default {
  components: {
    KRHeader,
    KRFooter,
    KRSideMenu
  }
}
</script>

<style>
#kr-main {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
</style>

作成したlayoutファイルを先程まで作っていた天気予報のページコンポーネントに適用します。

f:id:kojirooooocks:20181220015440p:plain

↑のような感じで設定すると、こんな感じで適用されます。

f:id:kojirooooocks:20181220015511g:plain

終わりに

今日は時間がなかったので、これで終わります。

次はライフサイクル周りと、ミドルウェア関連になります。

牛歩だけど進まねば。

お疲れ様でした。

Nuxt.jsビギナーズガイドを読んだ Vol.1

はじめに

こんにちは。

Kojirockの1人アドベントカレンダー Advent Calendar 2018の18日目の記事です。

体調が悪く1週間完全にダウンしていました。。。

アドベントカレンダーもまるまる抜けてしまって、残念極まりないです。

こういうときのために書き溜めしとかないとな、、、と思いました。

来年はこの反省を生かして必ず25日間書き続けられたらと思います。

で、今回からは、以下の本を読んで勉強できたことを記載していきます。

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

Nuxt.jsビギナーズガイド―Vue.js ベースのフレームワークによるシングルページアプリケーション開発

この本と同時に、 Nuxtの公式サイト も同時に確認しながら、手を動かしつつ進めていきました。

今回は、1章、2章のあたりを中心に勉強しました。

やってみた

1. インストール

本書では、前回のvueの本でも登場した Vue CLIでNuxt.jsのスターターテンプレートをインストールするという方法が紹介されていました。

今回は、公式サイトに紹介されている create-nuxt-app を使ってインストールしました。

$ mkdir nuxt
$ cd nuxt/
$ npx create-nuxt-app test_01
npx: 402個のパッケージを32.532秒でインストールしました。
> Generating Nuxt.js project in /path/to/study/nuxt/test_01
? Project name test_01 ← プロジェクト名
? Project description My exquisite Nuxt.js project ← プロジェクトの説明
? Use a custom server framework none ← サーバーサイドのフレームワークを選択
? Use a custom UI framework element-ui ← UI フレームワークの選択
? Choose rendering mode Universal ← SPAかuniversalモードかどうかの選択
? Use axios module yes ← axiosを使用するかどうかの選択
? Use eslint yes ← eslintを使用するかどうかの選択
? Use prettier yes ← prettierを使用するかどうかの選択
? Author name kojirock ← 作成者名
? Choose a package manager yarn ← パッケージマネージャの選択
Initialized empty Git repository in /path/to/study/nuxt/test_01/.git/
yarn install v1.12.3
info No lockfile found.
[1/4] 🔍  Resolving packages...
warning eslint > file-entry-cache > flat-cache > circular-json@0.3.3: CircularJSON is in maintenance only, flatted is its successor.
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > element-ui@2.4.11" has unmet peer dependency "vue@^2.5.2".
warning " > eslint-loader@2.1.1" has unmet peer dependency "webpack@>=2.0.0 <5.0.0".
warning " > eslint-plugin-vue@4.7.1" has incorrect peer dependency "eslint@^3.18.0 || ^4.0.0".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 180.40s.

  To get started:

    cd test_01
    yarn run dev

  To build & start for production:

    cd test_01
    yarn run build
    yarn start

インストールできたので実行してみます。

$ cd test_01
$ yarn run dev
yarn run v1.12.3
$ nuxt
ℹ Preparing project for development                                                                                                                                                                                                23:39:48
ℹ Initial build may take a while                                                                                                                                                                                                   23:39:48
✔ Builder initialized                                                                                                                                                                                                              23:39:48
✔ Nuxt files generated                                                                                                                                                                                                             23:39:48

✔ Client
  Compiled successfully in 6.89s

✔ Server
  Compiled successfully in 5.71s

ℹ Waiting for file changes                                                                                                                                                                                                         23:39:56

   ╭─────────────────────────────────────────────╮
   │                                             │
   │   Nuxt.js v2.3.4                            │
   │   Running in development mode (universal)   │
   │   Memory usage: 224 MB (RSS: 345 MB)        │
   │                                             │
   │   Listening on: http://localhost:3000       │
   │                                             │
   ╰─────────────────────────────────────────────╯

f:id:kojirooooocks:20181219030437p:plain

インストールできました。

2. ディレクトリ構造など

ディレクトリ構造は以下のとおりです。

$ tree -L 1
.
├── README.md
├── assets/
├── components/
├── layouts/
├── middleware/
├── node_modules/
├── nuxt.config.js
├── package.json
├── pages/
├── plugins/
├── static/
├── store/
└── yarn.lock

9 directories, 4 files

ディレクトリの用途は以下のとおりです。

  • assets

    • 画像やCSSなどを格納する
  • components

  • layouts

    • ページ全体のレイアウトテンプレートを格納する
    • ベーステンプレートという認識
  • middleware

  • pages

  • plugins

  • static

    • そのまま公開されてほしいリソースを格納する(favicon.icoなど)
  • store

    • Vuexストアを格納する

3. Routing

上記で記載したとおり、pagesはVue Routerの管轄内になります。

pages以下に、ディレクトリを切ってvueコンポーネントを配置していくと、それがそのままURLとなります。

つまり内部でVue Routerの設定などをよしなに作ってくれるということのようです。

例えば、pages以下のような感じでファイルなどを設置します。

$ tree pages/
pages/
├── README.md
├── index.vue
└── users
    ├── edit.vue
    └── index.vue

すると内部で自動的に以下のような感じのVue Routerの設定が作成されます。

routes: [{
  path: "/users",
  component: "pages/users/index.vue",
  name: "users"
}, {
  path: "/users/edit",
  component: "pages/users/edit.vue",
  name: "users-edit"
}, {
  path: "/",
  component: "pages/index.vue",
  name: "index"
}],

この設定は使用者は意識する必要がないので、この時点で実際にアクセスが可能です。

f:id:kojirooooocks:20181219030500p:plain

f:id:kojirooooocks:20181219030511p:plain

動的ルーティング

/users/:user_id のようにパラメータを使ったルーティングの定義も可能です。

動的ルーティングの場合は、_パラメータ名.vue というファイル名にする必要があります。

例えば今回の例の場合は、ファイル名は _user_id.vue としておく必要があります。

以下のような感じです。

$ tree pages/
pages/
├── README.md
├── index.vue
└── users
    ├── _user_id.vue
    ├── edit.vue
    └── index.vue

作成される設定は以下のような感じかと思います。

routes: [{
  path: "/users",
  component: "pages/users/index.vue",
  name: "users"
}, {
  path: "/users/edit",
  component: "pages/users/edit.vue",
  name: "users-edit"
}, {
  path: "/users/:user_id",
  component: "pages/users/_user_id.vue",
  name: "users-user_id"
}, {
  path: "/",
  component: "pages/index.vue",
  name: "index"
}],

これでアクセスが可能です。

f:id:kojirooooocks:20181219030530p:plain

ただ、現状 数字でも文字列でもなんでも _user_id.vue へ遷移してしまいます。

できれば数値のときのみに制限したいです。

こちらは公式サイトで乗っていたやり方のままですが、以下のようにroutingのバリデートを実行できます。

<template>
  <div>
    <p>
      users / user_id
    </p>
  </div>
</template>

<script>
export default {
  validate({ params }) {
    return /^\d+$/.test(params.user_id)
  }
}
</script>

f:id:kojirooooocks:20181219030545p:plain

user_idが数値以外の場合はルーティングが適用されてない事がわかります。

おまけ

こんな感じで動的なパラメータを使用してネストすることも出来ます。

また、渡されてきたパラメータを使用したい場合は以下のようにします。

$ tree pages/
pages/
├── README.md
├── index.vue
└── users
    ├── _party
    │   └── _user_id.vue
    ├── edit.vue
    └── index.vue
<template>
  <div>
    <p>
      {{ partyName }} / {{ userId }}
    </p>
  </div>
</template>

<script>
export default {
  validate({ params }) {
    if (!/^[A-Za-z]+$/.test(params.party)) {
      return false
    }
    return /^\d+$/.test(params.user_id)
  },
  computed: {
    userId: function() {
      return this.$route.params.user_id
    },
    partyName: function() {
      return this.$route.params.party
    }
  }
}
</script>

f:id:kojirooooocks:20181219030559p:plain

↑のようになります。

4. axiosを使用する

本書ではQiita APIを使用して、Qiitaから情報を取得する手順が丁寧に記載されています。

この方法を真似て、openweathermapから天気予報データを取得してみようと思います。

今回はインストール時にaxiosを使用するように設定しているので、nuxt.config.jsにはすでにaxiosの記述がmoduleの箇所に記載されています。

openweathermapから発行されるAPI keyを .envrc に記述して、 envを読み込むようにします。

ただし、openweathermapのAPIはQueryStringで送る形式のようなので、本書で紹介されている、axiosプラグインを作成してonRequestでリクエスト前にヘッダーを追加するといった機能は不必要なので省略しています。

.envrc
export OPENWEATHERMAP_API_KEY=XXXXXXXXX
nuxt.config.js
  env: {
    OPENWEATHERMAP_API_KEY: process.env.OPENWEATHERMAP_API_KEY
  }
pages/weather/index.vue
<template>
  <div>
    <p>只今の埼玉の天気</p>
    <span>{{ weather }}です</span>
  </div>
</template>

<script>
export default {
  async asyncData({ app }) {
    const weatherData = await app.$axios.$get(
      'https://api.openweathermap.org/data/2.5/weather?q=saitama,jp&APPID=' +
        process.env.OPENWEATHERMAP_API_KEY
    )

    return {
      weatherData: weatherData.weather[0].main
    }
  },

  computed: {
    weather: function() {
      if (this.weatherData === 'Clouds') {
        return '曇り'
      } else if (this.weatherData === 'Rain') {
        return '雨'
      } else if (this.weatherData === 'Snow') {
        return '雪'
      } else if (this.weatherData === 'Clear') {
        return '晴れ'
      } else {
        return this.weatherData
      }
    }
  }
}
</script>

f:id:kojirooooocks:20181219030633p:plain

表示されました。

今回使用したasyncDataは、nuxtが用意したvueのdataの拡張で、asyncDataの結果はdataにマージされます。

asyncDataはコンポーネントがロードされる前に実行されるもの(初期化前に実行されるもの)なので、aysncData内ではthisへのアクセスが出来ません。

asyncDataの第一引数に contextというデータが渡されるので、その中のappというルートのvueインスタンスからaxiosを呼び出すことが出来ます。

5. ページ遷移

先程作った天気予報に埼玉以外の天気を表示できるようにしてみます。

pages/weather/index.vue
<template>
  <div>
    <ul>
      <li><nuxt-link :to="`/weather/aomori`">青森の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/saitama`">埼玉の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/osaka`">大阪の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/hiroshima`">広島の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/okinawa`">沖縄の天気</nuxt-link></li>
    </ul>
  </div>
</template>
pages/weather/_pref.vue
<template>
  <div>
    <p>只今の{{ prefName }}の天気</p>
    <span>{{ weather }}です</span>
  </div>
</template>

<script>
export default {
  validate({ params }) {
    const availablePrefs = [
      'aomori',
      'saitama',
      'osaka',
      'hiroshima',
      'okinawa'
    ]
    return availablePrefs.indexOf(params.pref) !== -1
  },

  async asyncData({ app, params }) {
    const url = `https://api.openweathermap.org/data/2.5/weather?q=${
      params.pref
    }&APPID=${process.env.OPENWEATHERMAP_API_KEY}`
    const weatherData = await app.$axios.$get(url)

    return {
      weatherData: weatherData.weather[0].main
    }
  },

  computed: {
    weather: function() {
      if (this.weatherData === 'Clouds') {
        return '曇り'
      } else if (this.weatherData === 'Rain') {
        return '雨'
      } else if (this.weatherData === 'Snow') {
        return '雪'
      } else if (this.weatherData === 'Clear') {
        return '晴れ'
      } else {
        return this.weatherData
      }
    },

    prefName: function() {
      if (this.$route.params.pref === 'aomori') {
        return '青森'
      } else if (this.$route.params.pref === 'saitama') {
        return '埼玉'
      } else if (this.$route.params.pref === 'osaka') {
        return '大阪'
      } else if (this.$route.params.pref === 'hiroshima') {
        return '広島'
      } else {
        return '沖縄'
      }
    }
  }
}
</script>

f:id:kojirooooocks:20181219030743g:plain

いい感じで遷移しています。

遷移には、 <nuxt-link> を使用しています。

また、ほかの変更点としては、axiosでリクエストを飛ばす際に、urlパラメータを使用しているところくらいです。

6. メタの変更

タイトルやHTMLメタの修正の方法も本書に記載されています。

大本のタイトルの設定は nuxt.config.jsから行います。

  head: {
    title: pkg.name,
    titleTemplate: '%s | Kojirock Study Nuxt.js', ←追加

f:id:kojirooooocks:20181219030833p:plain

titleが変わりました。

ページごとにタイトルも設定できます。

pages/weather/index.vue
<template>
  <div>
    <ul>
      <li><nuxt-link :to="`/weather/aomori`">青森の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/saitama`">埼玉の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/osaka`">大阪の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/hiroshima`">広島の天気</nuxt-link></li>
      <li><nuxt-link :to="`/weather/okinawa`">沖縄の天気</nuxt-link></li>
    </ul>
  </div>
</template>

<script>
export default {
  head() {
    return {
      title: '天気予報'
    }
  }
}
</script>

f:id:kojirooooocks:20181219030846p:plain

変更されました。

以下のように、ページごとにtitleTemplateも書き換えることも出来ます。

export default {
  head() {
    return {
      title: '天気予報',
      titleTemplate: '%s|AAAAA'
    }
  }
}

f:id:kojirooooocks:20181219030900p:plain

終わりに

まだ最初ですが、vueの本を事前にやっていたおかげで、スムーズに入っていけている感があります。

次はvuexのところらへんからやっていきますー。

goのバイナリをlambdaにアップロードする

はじめに

こんばんは。

なんか毎回やりかたググってる気がしてるので、自戒を込めて、goバイナリのアップロード方法を記載しておきます。

こちらにもちょろっと記載してるんですが、改めてということで。

めちゃめちゃ簡単なまとめです。

やり方

バイナリ化

$ GOOS=linux GOARCH=amd64 go build -o ファイル名

zip化

$ zip ファイル名.zip zipにまとめたいファイル郡

※ 設定ファイルなどがある場合はそのファイルも一緒にzip化する

アップロード

zip化したファイルをlambdaの画面でアップロードします。

f:id:kojirooooocks:20181218034511p:plain

終わりに

おわりです。

go buildのところとか毎回ググってて、覚えが悪くて嫌になります。。。

現状この手順で上げてるんですが、他に良さげなやり方あったら教えてください。

PythonやNodeJSだとwebコンソール上のエディタで修正できるんですが、goの場合はアップロードが必要なんですよね。

新たに発表されたカスタムランタイムを使って、phpとかで書くのもありですが、go覚えるためにせっかくgoで書いたので、もうちょいやってみます。