nanisore oishisou

プログラマ、ララ・ベル子さん改めArm4さんのゆるふわ奮闘記。

Atomic DesignをVueコンポーネント設計に適用するために見るやつ

Vue Fes JapanのスライドでAtomic Designについて書いてあるスライドがあり、
コンポーネント設計であったもやもやが解決しそう!と思ってほんのり調べてみた。

コンポーネント設計にAtomic Designを採用したというスライド note.mu

▼Vue.js からみた AtomicDesign medium.com

▼Atomic Designを考案した人のブログ

bradfrost.com

そして、みんなで認識合わせる時には、発音しないといけないので
読み方と意味を調べてみた。
これが正しいかどうかは分からないので参考程度にお願いします。

Atom

  • 読み方:アトム
  • 意味:原子

【Molecule】

  • 読み方:モリキュール
  • 意味:分子

【Organism】

【Template】

  • 読み方:テンプレート
  • 意味:雛形

考案した人のブログにあるPageという概念は
デザイナーから見た個別のページと
デザインされるべきテンプレートを呼び分けるということなので
Vueのコンポーネント設計では存在しない、はず。

なるほどー!めっちゃ設計概念として分かりみある!!

Vue.jsの人気UIフレームワークまとめ2018秋

お久しぶりです。ベル子です。

Vue.jsのUIフレームワークについてのまとめ記事(英語)を見つけてツイートしたところ、
それなりにいいねがついたので
「みんな、UIフレームワークをめっちゃ探してるな」と感じとり
人気のあるフレームワークを日本語でまとめてみることにしました。

人気のあるフレームワークは以下のブログ記事などを参考にしています。

11 Vue UI Component Libraries You Should Know In 2018

海外のVue.js用UIフレームワーク紹介記事を読み漁り、どの記事にもだいたい出てきているフレームワーク
女の勘でチョイスしました。

人気がありそうなVue.jsのUIフレームワーク

Vuetify

vuetifyjs.com

Quasar

quasar-framework.org

Element

Element

Vue Material

vuematerial.io

BootstrapVue

bootstrap-vue.js.org

Buefy

buefy.github.io

どのフレームワークがどのくらい人気なの?

Star Historyを皆さんご存知ですか。
ちなみに私は知りませんでした。
githubのスター獲得の歴史をグラフで確認できるサービスです。

丁寧な解説記事はこちら。

Star history - GitHubのスター獲得履歴をグラフ化して比較できるWebサービス | ソフトアンテナブログ

そのStar Historyを使いまして、
女の勘で選んだベストフレームワークのスター獲得曲線を確認してみます。

Star history

見ておわかりのとおり、Elementは先発のVueのUIフレームワークで、スター数も飛び抜けて多いです。

どのフレームワークも右肩上がりでスターが増えていますね。
一度つけたstarをunstarすることってなかなかないと思うので、右肩上がりじゃないと逆に気になって夜も眠れませぬが、
見てお分かりのようにVueのフレームワーク自体の人気が急激に出てきているのがお分かりいただけると思います。

実は先発のフレームワークであるvue-materialも人気があったのですが、
こちらの曲線を見てお分かりのように後発のマテリアルデザインフレームワークである
Vuetifyが人気をかっさらっていってしまったようです。

Vue.js自体の人気について

ちなみにここで、世界三大jsフレームワークである、Vue.js、React、AngularのStar Historyも確認してみましょう。

Star history

ご覧になってお分かりのように、ついにVue.jsがReactを抜きました。(めでたいぜ!)

私がVueを初めた数年前はフロント界隈のイベントにおいてVue勢はややマニアック勢だったのですが、
もはや巷ではReactおじさんからVueおじさんへ変身しているおじさん勢も出てきています。

twitter.com

ごらん。女の勘を。
もはや、メインストリーム!!!!

Elementについて

ちなみに私はフレームワークは一通り候補を調べて人気があるものを、
使ってみて判断する派です。

それで2018年6月にVueのUIフレームワークを選定するにあたり、
当時最も人気と思われたElementとVuetifyを使ってみました。

2018年6月時点で、Elementはレスポンシブレイアウトに対応していない状態で
コンポーネントの詰め合わせという様相が強く統合的なフレームワークという感じではありませんでした。
そのため、レイアウトされたページの見本がなく、綺麗にレイアウトするのがかなり大変でした。

ということで、当時は結果的に楽で綺麗にレスポンシブ対応のレイアウトができるVuetifyを選択しました。

現在のElementのドキュメントを見る限りでは、
レスポンシブ対応されていて統合的なフレームワークとして使えそうに見えます。
アプリケーションに必要そうなコンポーネントもほぼ揃っているので
マテリアルデザインに抵抗がある人は使ってみてもよさそうだと思います。

github.com

リリースノートを見てみても活発に更新されてメンテナンスされているのが分かります。
一点、注意としては中国の方が開発されているので、突然中国語がドキュメントなどに登場したりします。

Vuetifyについて

Vuetifyは現在、本稼働案件で使用していますが、
目立った致命的なバグやレイアウト崩れなどはほとんどないように思います。
リリースノートを見てお分かりのとおり尋常じゃなく活発にリリースが行われています。

github.com

先日も新しいコンポーネントがリリースされました。
現在まで定期的にアップデートしていますが、
radioコンポーネントのイベントがinputからchangeになってしまったということ以外では
書き換えが発生するようなことはありませんでした。

一点注意点としてはVuetifyが採用しているcssプリプロセッサがstylusなのでstylusのloaderなどを入れたり
ファイルの分割などで少し工夫が必要かもしれません。

Vue.jsのUIフレームワークのデザイン分類

UIといえばデザインも非常に大事です。
デザインがアレなツールを使いたい人はあまりいないので、 できれば綺麗で好みのデザインに近いフレームワークを使いたいところです。
ということでデザインに着目して分類してみました。

マテリアルデザイン

  • Vuetify
  • Quasar
  • Vue Material

Bootstrap系

  • BootstrapVue
  • Buefy

独自デザイン系

  • Element

マテリアルデザインはレスポンシブ時の操作感まで考え抜かれていると感じることが多いです。
特に大きな時計が出てくるTimePickerは当初は正直「え、なにこれ。。」と思ったのですが
使い慣れてくるとスマホからでもPCからでも驚くほど素早く気持ちよく時間の入力ができます。

ただ、見慣れていないクライアントに「え、なにこれ。。」と言われてしまうかもしれないので
お好みで使っていただければと思います。

全体的にマテリアルデザインは洗練されている印象で、Bootstrap系は少しカジュアルな印象を与えます。
Elementについては、色が全体的に薄いのでオシャレ感はかなりありますが、
オシャレじゃなくていいからハッキリ見えるほうがいいというクライアント向けではなさそうです。

マテリアルデザインはよくアニメーションがついてくるので、それが煩わしいと感じる人もいるかもしれません。

フレームワーク選定について

ここで紹介したフレームワークコンポーネントがかなり充実しているものばかりなので
どれを採用しても良さそうな印象を受けます。

あとは、Vue.jsの場合はコンポーネントがいかにカスタマイズして使えるかということが重要になってくるので
その辺の使い勝手は多少、自分で使ってみて検討してみるのがいいです。

フレームワーク選定の時は、まずは人気があるものをリストアップし当たりをつけて、
ドキュメントなどを読み込んで絞り込み、
あとは実際に動かしてみて決めるというプロセスがいいように思います。

ドキュメントの出来がいいというのはフレームワークを選ぶ上でかなり大事です。
以下のポイントを重視するといいかなと思います。

  • 説明が分かりやすい。
  • 見本が豊富にある。
  • 概念の説明とAPIの仕様がきちんと分けて書いてある。
  • 目的の情報まで素早く到達できる。
  • 更新がマメに行われている。

今後も良さげなフレームワークが出てきたら紹介したいと思います★

Laravel 5.5で超絶便利なヘルパーoptionalってのできてるよ

この前、同僚にベル子たんに教えてもらったやつめっちゃ便利そうなのに何というヘルパーか忘れてしまいました!

と言われて、私も忘れてしまっていたという事件がありました。

現在、私がコアで開発してる案件は、5.7にアップデートしたので使えるのですが、
あまりにも"Trying to get property of non-object"を見すぎてしまったせいで
息を吸うように以下のように書いてしまいます。

<?php

$user_name = User::find(1) ? User::find(1)->name : '';

それか、php7で搭載されたnull合体演算子を使うともっと綺麗に書けます。

<?php

$user_name = User::find(1)->name ?? '';

何度も同じこと書かなくてよくなった!

PHP: 新機能 - Manual

これだけでも非常にありがたいのですが、
Laravel 5.5 で追加されたoptionalヘルパーを使うと息を吸うように
nullの時のエラーを回避できるようになります。

<?php

$user_name = optional(User::find(1))->name;

optionalを使うと、userが見つからなかった場合はnullを返して来ます。
厳密に空文字にしたい、などの時はnull合体演算子がいいかもしれません。

さらに Laravel 5.6.13 ではクロージャも第2引数で渡せるようになったらしいので
さらに使い勝手がよくなったっぽいいです。
すごい!さすが私のLaravel。

laravel-news.com

Laravelの公式ドキュメントはこちらです。

laravel.com

便利なものはどんどん使っていきたいところです。

git研修用スライド&Web API勉強会スライド

新卒が入って来た時に行ったgit研修用のスライドをSpeaker Deckで全世界に公開したので
Gitをこれから教えようと思ってるor初心からやり直したいという人がいたら参考にしてみてください。

あと8月のPG会で
初心者向けにWeb APIを超分かりやすく初歩の初歩から説明した際のスライドもアップしました。

話すことをすぐ忘れてしまうタイプなので
話すことをスライドに全部書いているため、スライドというか、もはや本w

あと時間管理ができなくて話しすぎるとよく言われてしまうので
これ以上は話さないぞという戒めでもあるw

git研修用は自分でも時々見返してしまうくらい頭がすっきりします。

ぜひ、ご一読ください!

VuetifyのDate Pickerを日本語化したら"日"ってついてくる、やだキモい

長い前置き(飛ばし読み推奨)

最近、フロント側を完全に脱jQueryして、Vue.js + Vuex + VueRouter + Vuetifyで開発を進めている。

これまでもVue.js + Vuex この2つは使っていたわけなんだけど
bootstrapベースであるAdminLTEと組み合わせることに限界を感じていて、
それぞれの開発者がVueライブラリを探して入れてみたり、
自作してみたりみたいなことを、それぞれの案件で繰り返していたわけだ。

心の声(もう、こんなお飾りのjQuery依存のUIフレームワークなんて実際は足枷じゃねーか。確かにデザインは綺麗なんだけど。。)

そこで出会ったのがVuetify。

少し使い込んでみた感じ、グリッドレイアウトにflexboxを採用しているので
レイアウトに苦戦することもあるけど、それだって新しいbootstrap4も同じだし
もはや、これが時代の流れなのかもしれないと思い、思い切って使ってみることにした。

エンジニアは、手を動かさなくなったら
時代に置いていかれて、すぐに周りについていけなくなる。
これは私がしばらくエンジニア業から離れたときに、痛いほど感じたことだ。
久しぶりに会ったエンジニアの知人の言っていることが分からなかった。

別に毎日懸命に手を動かして勉強する必要はない。
ただ、ニュースを毎日見るように、
ご飯を毎日食べるように、
時代の流れだけは把握しておかないといけない。
エンジニアとは、そういう生き物だ。そう感じた。

話が脱線しすぎた。元に戻そう。

Vuetifyを採用してみて最初は、
使い慣れないこととドキュメントの多さにグロッキーになっていたが
いくつか実装してみると、だいぶ手に馴染んできた。
アニメーションが綺麗でデザインも綺麗。
動きもサクサク。

モックを作成しPMに見せたら、いたく感動してくれた。

よかった。間違ってない。何となくそう思えた。
いいデザインは、人の心を魅了する。
いいデザインは、高品質を演出する。
いいデザインは、そのプロダクトを作った人間の情熱を伝えることができる。

要するに、
Vuetifyっていいね!

本題

Vuetifyのコンポーネントは、かなりいろいろ気が利いている。
色を変えるのも、デザインをカスタマイズするのも設定一つでできてしまう。

しかし、日本語化したDate Pickerだけは(あとTime Pickerもなんだけど。。)
ちょっとキモい部分がある。

f:id:arm4:20180817154130p:plain
日本語化したDate Picker

え?何この"日"ってやつ。
しつこいwwwwwwwww

消したかったけどoptionにday-formatはあるけどdate-formatがない。

いろいろ検索してみたらこんなcodepenを発見。

codepen.io

あれ?day-formatで指定すればいいっぽい?

ためしにday-formatに以下を設定してみたところ、
しつこい"日"は消えてくれました。

    <v-date-picker
      v-model="picker"
      :landscape="landscape"
      :reactive="reactive"
      locale="jp-ja"
      :day-format="date => new Date(date).getDate()"
    ></v-date-picker>

f:id:arm4:20180817154555p:plain
日よ、消え去れ!

めでたし、めでたし。

Homebrew を updateしたら、php -vでdyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dylibと言ってくる

タイトル長っw

個人的に使ってみたことのあったyarnなんですが、本案件で使おうよとなると
yarnというものがありましてから始まり、こういう面で嬉しいんですねと続き、
それをPMに承認してもらって、じゃあそれをメンバーに周知して、と
いろいろ根回しが必要で面倒なので、npmのままやってたんですね。

あと別にnpmでも困らないので、正直。

しかし、新しいプロジェクトでは使いたいなーと思っていた矢先に
「駅前に新しく出来たプロジェクトがあるんだけど、俺たちも一緒にyarnにしませんか?」と
コミュ強なPMからお誘いされたんで、そうしてあげることにしました。
ライブラリのインストール速くてラクラクだねー。
バージョンもロックされて安心だしー。
あと、別にこれ途中からyarnにしても何の問題もないなー。yarn addすればyarn.lockも勝手に出来るし。(←知らなかったw)
yarn最高やーん。布教しよw

で、これからが本題なんだけど、
先日High Sierraクリーンインストールした関係で
yarnをinstallしなくちゃならなかったのでhomebrew updateしてhomebrewでインストールしたわけです。

したら、nginxさんから"502 Bad Gateway"とか怒られるようになって、
なんでやろかーといろいろと探っていたところ、php がエラってることが分かりました。 PHPを複数バージョン入れてるからだと思うんだよね。。。

またこれかよ。もうphpenvみたいなの使ったほうがいいかも。

それを辛うじて修正できたので、ここで手順を晒しておきます。

ちょっとワーニングまで直せてないんだけど。
直したので後述するぜ。

PHPを復活させるまでのベル子の軌跡

homebrewのupdateを実施したところ、phpがエラーを吐くようになった。

具体的には以下のエラー。

[-] php -v
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dylib
  Referenced from: /usr/local/bin/php
  Reason: image not found
[1]    2282 abort      php -v

同じことで困っている人を発見。

kimikimi714.hatenablog.com

phpの再インストールが必要と書いてあるが、参考のstackoverflowにはsymlink方式とbrew unlink libpng方式もあるので まずはそちらから試すほうをおすすめする。理由は後述。

この人が参照しているstackoverflowはこちら

stackoverflow.com

ということで私は思い切ってphpを再インストールしてみた。 再インストールはオススメしない。理由は後述。

brew reinstall php72

そして、php -vをすると

[~] php -v
PHP Warning:  PHP Startup: Unable to load dynamic library 'memcached.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so, 9): image not found)) in Unknown on line 0

Warning: PHP Startup: Unable to load dynamic library 'memcached.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so, 9): image not found)) in Unknown on line 0
PHP Warning:  PHP Startup: Unable to load dynamic library 'imagick.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so, 9): image not found)) in Unknown on line 0

Warning: PHP Startup: Unable to load dynamic library 'imagick.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so, 9): image not found)) in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

いっぱいエラーが出た。

探してみると/usr/local/Cellar/php/7.2.6ではなく/usr/local/lib/php/pecl/20170718配下にある。

[~] sudo find / -name imagick.so
/usr/local/lib/php/pecl/20170718/imagick.so

php.iniを書き換える

vi /usr/local/etc/php/7.2/php.ini
extension_dir = "/usr/local/lib/php/pecl/20170718"
;extension_dir = "/usr/local/Cellar/php/7.2.6/pecl/20170718"

php -vしてみるとまだなんかエラーを吐いているが、一応phpは動くようになった。

[~] php -v
PHP Warning:  Version warning: Imagick was compiled against Image Magick version 1799 but version 1800 is loaded. Imagick will run but may behave surprisingly in Unknown on line 0

Warning: Version warning: Imagick was compiled against Image Magick version 1799 but version 1800 is loaded. Imagick will run but may behave surprisingly in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

※ 7/13追記

Imagickを入れ直す

[~] pecl uninstall imagick
[~] pecl install imagick

php -vをして以下のようなエラーが出たら、php.iniにモジュールロードが二重で書かれているので、
一行削除する。

[-] php -v
PHP Warning:  Module 'imagick' already loaded in Unknown on line 0

Warning: Module 'imagick' already loaded in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

phpの再起動を忘れずに。

sudo brew services restart php

こんな感じで直るは直るけど気持ち悪いワーニングが出るので、再インストールは最後の手段にしたほうが良さげ。
あとマイナーバージョンが変わってまうし。

v-modelをちゃんと理解し、Vue-select+Vuexで実装する方法、そして好みの引数を渡す方法

あなたは覚えているだろうか。この記事を。

arm4.hatenablog.com

そう。Vuexを導入するとv-modelは使えなくなる。

これは、v-modelではstoreのstateを直接書き換えに行ってしまうためだ。
そのため、上記のようにして自前でstateの値と同期が取れるように書いてやる必要性がある。

ライブラリを導入しようと思うと、だいたいサンプルのコードにはv-modelが登場してくるので
Vuex初心者は困惑してしまう。

これも、上記のv-modelとは要するに何をしているのかということを理解することで ライブラリのサンプルのコードを自前で書き直すことができるようになる。

v-modelとはつまり何か

まずはこちらのv-modelについての公式の解説を見てもらいたい。

jp.vuejs.org

<input v-model="searchText">

イコール

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

この原理を利用してVuexのstoreのステートをセットするようにしているのが、
私が前に書いた記事の手法である。

それからライブラリに登場する際のv-modelを理解するのに重要なのが、以下の部分。

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

要するにカスタムコンポーネントを使っている場合の挙動はこちらになる。

ここでたぶんみんな思うことは一つだと思う。

searchTextに代入している$eventとは一体何ですか?

jp.vuejs.org

コンポーネントでイベントをリッスンすると、送出されたイベントの値に $event でアクセスできます:

要するに子コンポーネントでinputというカスタムイベントを発行し、
そこで本当のネイティブイベントのvalueを親に渡しているということだ。

Vue-selectはカスタムコンポーネントで実現されているので、
この挙動を理解することで自分が意図したように実装することができる。

Vue-selectって何?

sagalbot.github.io

要するにVue版のSelect2だ。

Vue-select+Vuexの実装方法

Vuexを使っている際の実装方法は実は公式ドキュメントに記載がある。

Vuex · vue-select

このような実装だと、毎度毎度setActivePersonのようなメソッドを書かなくてはいけなくなるので
できれば私が書いた記事のようにkey_nameを渡したら勝手にsetしてくれるような汎用的なメソッドを通したいところだ。

そのためには、key_nameを渡すようにしたいが、
引数を渡すとvalueが渡されてこない。

ここにkey_nameを渡すには、仕組みが分かっていないと渡せない。

ここでさっきの知識が生きてくる。

Vue-selectは、選択された値が変わるとon-changeというプロパティに設定したcallback関数が実行される仕組みになっている。

github.com

デフォルトでは以下が設定されている。

      onChange: {
        type: Function,
        default: function (val) {
          this.$emit('input', val)
        }
      },

自前のinputカスタムイベントを発火することで、v-modelを使ってデータが同期されるようにしているようだ。

公式サイトに書いてあったカスタムコンポーネントの作り方と同じ手法だ。

ここでもう一度v-onのおさらいをする。

jp.vuejs.org

通常の要素上で利用した場合、ネイティブ DOM イベント だけ購読します。カスタム要素コンポーネント上で利用した場合、子コンポーネント上での カスタムイベント の発行を購読します。

ということで、inputタグで@inputとするのとv-selectタグで@inputと書くのは
もともと全然意味が違う。

@inputでVue-selectが発行しているカスタムイベントをリッスンし、$eventでそのイベントが渡してくるデータを拾う。

<v-select 
    multiple
    label="email"
    @input="updateValue($event, 'active_peaple')"
    :options="$store.state.people"
    :value="$store.state.form.active_peaple"
  ></v-select>

このようにすると、思い通りkey_nameが渡せるようになる。

実際に実装してみたコードは以下だ。

codepen.io

v-modelとカスタムコンポーネントの仕組みを理解することで、
カスタムコンポーネントとして実装するタイプのコンポーネントをVuexで思い通りに実装するやり方が分かるようになると思う。

これからVuexやるよって人は、 難しいと思わずにしっかり抑えておいて欲しい!