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

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

Vue.js入門 基礎から実践アプリケーション開発までを読んだ vol.10

はじめに

こんにちは。

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

以下の本を読んで勉強できたことを記載していきます。

今回は第10章です。

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

前回の懸念の通り本章は、コードを写経する事が多かったので、あまり載せられることがありませんでした。

なので今回は、javascriptユニットテストの方法をピックアップしようと思います。

やってみた

jsのテストコードはほぼほぼ書いたことなかったので、勉強になりました。

本書では プロジェクト作成は vue init でテストツールは mocha だったのですが、自分で作成したものは

vue create + jest となっています。

以下は、今回のサンプルアプリケーションの1つのコンポーネントである KbnButton.vue です。

KbnButton.vue

<template>
  <button
    :class="classes"
    :disabled="disabled"
    type="button"
    @click="handleClick"
  >
    <slot />
  </button>
</template>

<script>
export default {
  name: 'KbnButton',

  props: {
    type: {
      type: String,
      default: 'button'
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    classes() {
      const cls = this.type === 'text' ? ('-' + this.type) : ''
      return [`kbn-button${cls}`]
    }
  },

  methods: {
    handleClick(ev) {
      this.$emit('click', ev)
    }
  }
}
</script>

<style scoped>
.kbn-button {
  padding: .6em 1.3em;
}
.kbn-button-text {
  border: none;
  padding-right: 0;
  padding-left: 0;
}
</style>

このコンポーネントを、プロジェクト作成時にできている example.spec.js を参考にテストコードを作成しました。

それが以下です。

KbnButton.spec.js

import { mount } from '@vue/test-utils'
import KbnButton from '@/components/atoms/KbnButton.vue'

describe('KbnButton.vue', () => {
  it ('kbn-buttonクラスを持つbutton要素で構成されること', () => {
    const wrapper = mount(KbnButton)
    expect(wrapper.is('button')).toEqual(true)
    expect(wrapper.classes()).toContain('kbn-button')
  })

  it ('kbn-button-textクラスを持つbutton要素で構成されること', () => {
    const wrapper = mount(KbnButton, {
      propsData: { type: 'text' }
    })
    expect(wrapper.is('button')).toEqual(true)
    expect(wrapper.classes()).toContain('kbn-button-text')
  })

  it ('disabled属性が付与されていること', () => {
    const wrapper = mount(KbnButton, {
      propsData: { disabled: true }
    })
    expect(wrapper.is('button')).toEqual(true)
    expect(wrapper.attributes().disabled).toEqual('disabled')
  })

  it ('クリックイベントが発行されていること', () => {
    const wrapper = mount(KbnButton)
    wrapper.trigger('click')
    expect(wrapper.emitted().click.length).toEqual(1)
  })

  it ('スロットにコンテンツが挿入されていること', () => {
    const wrapper = mount(KbnButton, {
      slots: { default : '<p>hello</p>' }
    })
    expect(wrapper.text()).toEqual('hello')
  })
})

実行すると以下のようになります。

$ yarn vue-cli-service test:unit
yarn run v1.12.3
$ /path/to/node_modules/.bin/vue-cli-service test:unit
 PASS  tests/unit/specs/components/atoms/KbnButton.spec.js
  KbnButton.vue
    ✓ kbn-buttonクラスを持つbutton要素で構成されること (23ms)
    ✓ kbn-button-textクラスを持つbutton要素で構成されること (2ms)
    ✓ disabled属性が付与されていること (2ms)
    ✓ クリックイベントが発行されていること (3ms)
    ✓ スロットにコンテンツが挿入されていること (11ms)

Test Suites: 1 passed, 1 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        1.788s, estimated 2s
Ran all test suites.
✨  Done in 3.19s.

単純なテストだったので、実行方法も記述方法もそこまで難しくありませんでした。

ただ、一点わからなかったことが、example.spec.js で使用されていた shallowMount() と、本書のテストコードで使用されている mount() の違いでした。

調べると以下の説明がとてもわかり易かったです。

コンポーネントをレンダーする二つのメソッド - mountとshallowMount

shallowMount は通常のhtml要素をレンダーしますが、Vue componentsに対しては描画せずスタブに置き換えることが分かりました。

こちらでも書いているのですが、axiosで通信している部分などをスタブに置き換えることができるみたいです。

今回みたいなatoms単位のコンポーネントユニットテストの場合は mount() で問題ないと理解しました。

終わりに

簡単ですが、以上です。

流石にその日中にpostしきれなくなりました。。。

ただ、25日分は確実にやり遂げようと思います。

次からは、nuxtの本に移ります!!

ではまた~。

write_blog_every_weekから大事なお知らせ

当初人数が集まらなくても、個人slackでやるからいいや。

というくらいのノリで始めた、write_blog_every_weekですが、現在多くの方に参加してもらい、50名近くのユーザーが参加するslackチームとなりました。

大変嬉しいことなのですが、人数が増えたことにより、週に約50本近く更新されてしまうことで、みんなのブログをきちんと読みきれないという声が上がったり、有志による運営の手も回らない状況になってしまいました。

上記のような現状を鑑みて、この度、招待リンク経由の自由参加型を廃止しました。

離脱者が出ることは望んでいませんが、Slack内のルールとして更新が滞った場合に強制退会となるケースが有り、人数が減ってきましたら再度募集するような流れを検討しております。

理念に共感していただいたにもかかわらず、現在ご入会いただけないこと大変申し訳なく感じています。よろしくお願いいたします。

Vue.js入門 基礎から実践アプリケーション開発までを読んだ vol.9

はじめに

こんにちは。

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

以下の本を読んで勉強できたことを記載していきます。

今回は第9章です。

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

中規模・大規模向けアプリケーション開発② 設計

目次

9.1 コンポーネント設計

9.2 単一ファイルコンポーネント

9.3 状態モデリングとデータフローの設計

9.4 ルーティング設計

9.1 コンポーネント設計

ここでは、今回作成するタスク管理アプリケーションのコンポーネント設計の方法が述べられています。

最初の手順として、Atomic Designに準拠した設計手法によるコンポーネント抽出を行います。

今回の場合は以下のような分け方になるようです。

粒度 コンポーネント
Atoms ラベル、テキストボックス、ボタン、アイコン
Molecules ログインフォーム、ボードナビゲーション、タスクリストヘッダー、タスクフォーム、タスクカード、タスク詳細フォーム
Organisms タスクリスト、ボードタスク
Templates ログインビュー、ボードビュー、タスク詳細モーダル
Pages ログインページ、ボードページ、タスク詳細ページ

Atoms

最小粒度で、これ以上の分割ができないものが対象です。

今回でいうと、テキストボックスやボタンなどは、これ以上の分割ができないものなので、それぞれが該当します。

Molecules

もろキューみたいな読み方ですが、マリキュールというみたいです。

Atomsを組み合わせたコンポーネントです。

ログインフォームでいうと、ラベル、テキストボックス、ボタン、アイコンなどまさにAtomsとして分割したコンポーネントが組み合わさって作られています。

Organisms

Atoms, Moleculesそして、同レイヤーのOrganismsを組み合わせたコンポーネントです。

イメージ的には、Organismsからが、ドメインレイヤーという感じなのでしょうか?

Templates

Atoms, Molecules、Organismsを組み合わせたコンポーネントです。

本書ではTemplatesはワイヤーフレームと表現されています。

9.2 単一ファイルコンポーネント

SFCでそれぞれ分割抽出したコンポーネントを作成していきます。

ここからは写経になります。

重要な点として、コンポーネント名(ファイル名)は、各プロジェクト毎(ベンダー毎?)のプレフィックスをつけることを推奨されています。

外部ライブラリを使用した際、コンポーネント名がかぶらないようにするためです。

9.3 状態モデリングとデータフローの設計

ここからは、今回のアプリケションで使用するデータ設計を行います。

ツールとしてはVuexを使用します。

本書で紹介されている状態は以下のとおりです。

状態 詳細
Auth 認証情報
Task タスク情報
TaskList タスクリスト情報
Board ボード情報

上記はトップレイヤで、それぞれの状態に更にデータがひも付きます。

例えば、Authの状態であれば、 token userId などを持っています。

各状態への変更(mutation)へアクセスするためのactionの定義になります。

例えば

  • Authにアクセスするためのloginアクション
  • タスクリストにアクセスするためのfetchListsアクション

などです。

9.4 ルーティング設計

最後にRouting設計ですが、こちらはもちろん Vue Routerを使用します。

今回作成する各種ルートの設定が記載されています。

終わりに

今回も前章と同じく、テキストのみの少々薄い内容となってしまいました。

次章がメインの開発になりそうです。

また、次章は写経がメインになりそうなので、こういった形式ではなく、気になったところをピンポイントで紹介していくスタイルになる可能性があります。

それか、本書では Vue CLIinit で作成しているので、 create で作成した手順を記載する可能性があります。

とりあえず今回はここまで。

おしまい。

今年の振り返りと来年の目標

はじめに

こんばんは。 この記事は真・エンジニアの登壇を応援する会 Advent Calendar 2018 9日目の記事です。

この記事では、自分の振り返りと来年の目標をKPTとして書いてみます。

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

本題

Keep

1. 週に一回ブログを書くという絶対ルールを守れた

f:id:kojirooooocks:20181206041723p:plain

昔から何をやっても長続きしなかった自分が、 @kakakakakku さんが出演している 伝説のPodcast を聴いてから、なにやらスイッチが入り、1年間続けることができました。ブログに関しては、今月はもちろん、来年からも続けるつもりですが、とりあえず、最初に決めたルールを守れた自分をただただ褒めたいと思います。

2. ブログを書くという目標が生まれたため、仕事以外の時間を積極的に勉強に当てることができた

勉強しようしようと思っていても、仕事が終わると、ついついyoutubeみたりネットサーフィンしたりしてたのですが、ブログを必ず週一回書くというルールができたため、気になってた技術を少しでもいいから触ってみるとか、自分の得意分野の派生技術とかを触ってみようとか、逆に苦手分野を挑戦してみようとか、内容的には大したことなくても、必ずチャレンジし、その結果をブログにしていました。

そのため、ぼけーっとyoutubeを見てる無駄な時間は、ほぼほぼなくなり、インプット・アウトプットを増やし続けることができました。

3. ブログを週に一回必ず書こうというSlackチームを作ったこと

絶対ルールを守って頑張って書いていたのですが、モチベーションが落ちて、絶対ルールが守れなくなりそうになっていた時期がありました。

モチベーションが落ちている理由ってなんなんだろうなと考えたところ、結局自分との戦い的なところがありそうだなと思いました。

自分との戦いに敗北しかけているから、モチベーションが下がっているんだろうなと。

それって自分ひとりで戦っているから辛くなっているのかなと思ったので、同じ仲間を作ろうと思い、今年の9月に 週一でブログを書くSlackチーム を作りました。

自分が書いたブログを見てくれて、時には指摘してくれて、書けそうにない場合は応援や煽ってくれて、とにかく刺激をもらています。

メンバーは自分なんかより遥かにすごい方たちばかりなので、一定の緊張感もありつつ、とても刺激をもらえるので、本当に作ってよかったなと思います。

Problem

1. あまりにも手広くやりすぎた

ブログを書くという名目があったため、最初の方は進め方が微妙にわかってなくて、とにかくいろんな言語触ってみようと横に広げすぎてしまいました。

結局浅い知識のまま、復習する前にまた別言語、別ツールと飛び飛びで触っていたので、結局少ししか身になっていないという悪いループにハマっていました。

これに気づいてからは、自分がやりたい言語などを絞ろう(JavascriptGolang)と思いました。

2. 家族に遠慮して、勉強会へ参加しないようになった

現在1歳3ヶ月になる子供がいて、奥さんが率先して子育てをしてくれています。

自分も手伝えるときは手伝っているのですが、やはりメインの戦力としてはやっていけないです。

なので、せめて奥さんが助けてほしいときになるべく傍にいようと思い、勉強会はなるべく参加しないようにしていました。

なんとなく自分の中でももやもやしていた部分があったので、奥さんにそのことを相談したら

「勉強したいんだったら、遠慮せず行ってきていいよ!」

という男前な返しが来ました。

自分の中にためず、家族には相談すべきだなと思いました。

Try

こちらは箇条書きで書いてみます。

  1. Javascript力(Vue, React)をつける

  2. Golang力をつける

  3. 簡単なものでいいからOSSへ貢献したい

  4. 3回以上登壇したい(うち一回は簡単なものでも良いから技術系で登壇したい)

  5. 1ヶ月以上の積本を作らない

  6. イベントを開催してみたい

終わりに

もっと少ないかなと思いましたが、意外と書くことありました。

総括すると、去年にはアウトプットを積極的にしていこうという年だったのですが、来年はアウトプットの質を高めていこうという年になるかなと思っています。

積極性は変わらず、登壇然りブログ記事しかり、質を今年以上のものにして、アウトプットしていきたいと思います。

前述したSlackチームで作ったアドベントカレンダーもありますので、よかったらそちらも見てください(笑)

以上です。

ありがとうございましたー!

書き続けることが大事

f:id:kojirooooocks:20181206055245j:plain

はじめに

こんばんは。 この記事はwrite-blog-every-week Advent Calendar 2018 9日目の記事です。

前回は @konosumi さんの記事でした。

ブログを書き続けるための工夫とモチベーションを維持するための取り組み

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

write-blog-every-weekってなに? というかたはこちらの記事をご参照ください。

久しぶり家で飲んで、まとまらない記事になっちゃうかもしれませんが、よろしくおねがいします。

本題

このslackチームは週一回必ずブログ書こうねという絶対ルールがあります。

ユーザーはjoin後自分のブログを登録します。

自身のブログを登録したら、いきなり妖精さんが煽ってきます。

f:id:kojirooooocks:20181209000234p:plain



ブログを書けていないユーザーは、以下のように全体通知で発表されます。


ブログを書いても、新しい週が始まったら、再度書く記事数がリセットされて、通知されます。

ここまでは少し怖いですが、もちろんメリットがあります。

slack上ですぐにフィードバックがくるので、リアルタイムで知識の修正が行えます。

あと、単純に見てくれている人がいるんだということでモチベーションの低下がふせげます。

ブログを書けていない人には、強制退会にならないよう煽ったりもします。

主観的な意見ですが、このslackチームに入ってくれている人たちは、レベルがとても高いなと思っています。

slackに技術的な相談をしたときも、いろんな意見を出してくれて、とても頼りになります。

本当に自分より遥かにすごい人達ばかりが集まっていますw

そういった意味で

「しょうもないブログあげちゃってもなぁ。。。」

とか。

「うわっ(○○さんと比べて)俺のブログのクオリティ低すぎ・・・!」

とか、時々考えちゃうこともあります。

もしかしたら、おんなじことを考えているメンバーもいるかも知れません。



ただ、それってすごくもったいないです。

そんな事気にしてる暇があれば書けばいいんです。

しょうもない記事(クソ記事)になっちゃっても、まず書くこと。

表題にも書きましたが、書き続けることが大事なんですよね。

いきなりいいものを作ろうとしなくていいんです。

質が良いものをあげようとして、作り込むのに時間かかって途中で燃え尽きちゃうっていうケースってよくありますよね。

そうならないためにも、とりあえず書いて、出しちゃえばいいんです。

確かにアウトプットの質(ここでいうとブログ記事の質)を高めていくことって大事だと思うんですが、それって書くことが習慣化された後でいいかなと思っています。

量は質に転化する

@t_wadaさんの以下のスライドで乗っている1文です。

これってブログにも言えると思います。

Mozyさんの記事にも書いてありましたが、

そもそも世界に何も生まれないよりは、しょぼいものでも書いた方がいいと思って Done is Better than perfect の精神で記事を書くことにしています。

まさにこれだとおもいます。

そして、それを続けることが一番大事だなと思います。

ブログ書くことってメリット多いんです。

ブログって続けているだけで、「継続力がある人なんだな」「勉強意欲がある人なんだな」という2点を、外部に示せるんです。

それってすごい簡単で、すごい得ですよね。

さらに質が高まれば、「文章力のある人だな」

内容によっては「技術力のある人だな」とどんどんメリットがついてきます。


今から、ブログ書こうとしている人、もしくはブログ書き続けるのを諦めてしまった人は、とにかくしょうもない記事でもなんでも書き続けることを頑張ってみてください。

そして、どうしても続けられないと感じたら、ぜひ write-blog-every-week に入ってみてください。

前述したとおり、メンバーがブログを続けられるようなインフラが整いつつありますし、書くことがないなんていうときも、チームにはネタ出しチャンネルがあり、みんなで続けられるようにネタを出し合ったりしています。

一人じゃダメでもみんなと一緒なら続けられるかもしれません。

終わりに

うまくまとまらなかった。。。

明日は最近チームにjoinしてくれた nitt-san さん です。

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

Vue.js入門 基礎から実践アプリケーション開発までを読んだ vol.8

はじめに

こんにちは。

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

以下の本を読んで勉強できたことを記載していきます。

今回は第8章です。

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

中規模・大規模向けアプリケーション開発① 開発環境のセットアップ

目次

8.1 Vue.jsのプロジェクト構築の特徴

8.2 本章で作成するアプリケーション

8.3 アプリケーションの開発環境構築

8.4 Vue CLIによる開発環境の構築

8.5 アプリケーションのビルド

8.6 テスト環境

8.7 フロントエンド・バックエンド連携

8.8 さらなる開発環境の強化

8.1 Vue.jsのプロジェクト構築の特徴

大規模アプリケーションのプロジェクト構築に向けての話が記述されています。

ここは概要程度でしたので、流し読みしました。

8.2 本章で作成するアプリケーション

今回作成するアプリケーションの説明が記述されています。

Trelloのようなタスク管理アプリケーションになります。

仕様や、ページのレイアウト画面参考図などが記載せれています。

モックを作成して、バックエンド連携も擬似的に行うので、axiosを使用することになります。

8.3 アプリケーションの開発環境構築

Vue CLIで環境を作成します。

本書では、Vue CLIのinitコマンド(vue init)を実行していますが、tipsとして、vue initはレガシーコマンドとなっており、 前章でも使用した、vue createの使用が推奨されています。

今回は、本書に沿って一から プロジェクトを作成します。

8.4 Vue CLIによる開発環境の構築

vue create で作成したので、本書のプロジェクトツリーとは違いますが、このような感じで作成しました。

$ tree -L 2 -I 'node_modules' .
.
├── README.md
├── babel.config.js
├── cypress.json
├── jest.config.js
├── package.json
├── postcss.config.js
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── App.vue
│   ├── assets
│   ├── components
│   ├── main.js
│   ├── router.js
│   ├── store.js
│   └── views
├── tests
│   ├── e2e
│   └── unit
└── yarn.lock

8 directories, 13 files

8.5 アプリケーションのビルド

こちらのブロックでは、ビルドに必要なwebpackなどの説明があります。

また、linterの実行などの説明があります。

今回は vue createで作成したため、若干構成が違います。

vue createでの作成だからだとは思いますが、package.jsonのscriptsにそれぞれのスクリプトが登録されています。

  • yarn serve => サーバーたちあげ
  • yarn build => ビルド実行
  • yarn lint => lint実行
  • yarn test:e2e => e2e test実行
  • yarn test:unit => unit test実行

8.6 テスト環境

フロントでのテストツールの説明が記載されています。

ここでは具体的な方法は、記述されていません。おそらく次章で出てくるのだと思います。

jsのテストは自分は、何年か前に書いた記憶があるのですが、完全に忘れているので、これを気に学び直したいです。

8.7 フロントエンド・バックエンド連携

バックエンドとの連携関しての概要が記載されています。

このあたりはどちらかというと、自分が得意としている分野だったので、流し読みしました。

8.8 さらなる開発環境の強化

ここで紹介された以外の開発を進める上での便利なツールを紹介されています。

ただ、 vue createでプロジェクトを作れば、紹介されている大体の機能が入ってしまいますので、流し読みでも大丈夫だと思います。

2点だけ、モックとしてのjsonを返すバックエンドサーバーと、chromeのaddonであるVue DevToolsは入れておくべきです。

バックエンドサーバは、 json serverとかでとりあえず代用するのでも大丈夫だと思います。

終わりに

今回は、非常にかんたんに終わりました。

次章のための用意という感じです。

テストの書き方などは学び直したいと思っていたので、次章は気合を入れて取り掛かりたいと思います。

ではでは。

Vue.js入門 基礎から実践アプリケーション開発までを読んだ vol.7

はじめに

こんにちは。

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

以下の本を読んで勉強できたことを記載していきます。

今回は第7章です。

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

Vuexによるデータフローの設計・状態管理

目次

7.1 複雑な状態管理

7.2 データフローの設計

7.3 Vuexによる状態管理

7.4 Vuexのコンセプト

7.5 タスク管理アプリケーションの状態管理

7.6 ストアのモジュール分割

7.7 VuexストアとVueコンポーネント間の通信

7.8 VuexとVue Routerの連携

7.1 複雑な状態管理

このブロックでは、タスク管理のアプリケーションを例にとって、Vuexを使用せず、データフローのことを考えない場合、どのような辛みがあるのかを完結に説明されています。

7.2 データフローの設計

単方向データフロー・双方向データフローについてが説明されています。

このあたりの説明は、公式サイトのほうが簡素かつわかりやすく纏まっていたような気がします。

https://vuex.vuejs.org/ja/

単方向データフローにするメリットとして、本書で紹介されていた以下の文もイメージしやすかったです。

データを取得しつつ更新するといったようなことができなくなり、実装やデバッグが単純になる。 データを取得、更新するために何をするかの選択肢が絞られて、理解が容易なコードを書きやすい。

7.3 Vuexによる状態管理

vuexを使用するメリットなどが述べられています。

実際のインストール方法も乗っています。

今回は、前回の記事で使用した Vue CLIでVuexをすでにインストール済みでしたので、飛ばします。

Vue CLIでインストールしたVuexのファイルの中身は以下です。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {

  }
})

7.4 Vuexのコンセプト

表題の通りVuexのコンセプトについて述べられています。

以下の一文が気になりました。

Vuexはライブラリとしての機能だけではなく、実際のパターンも含めてVuexであるという見方をすべきです。

ストア

アプリケーションの状態を保持する役割を持っています。

上記に記載しているスクリプトexport default new Vuex.Store({ となっていますね。

ストアの構成要素は以下の4つということです。

  • State

    => アプリケーションのステート(状態)

  • Getter

    => 状態の一部や、状態から計算された値を返すゲッター

  • Mutation

    => 状態を更新できる

  • Action

    => 外部APIとのやり取りを行う

基本的にストアはアプリケーションに1つ持つということですが、大規模なプリケーションの場合はストアを モジュール という単位で分割して管理することもできるようです。

ステート

前述したとおり、アプリケーションの状態をオブジェクトで持っています。

Vuexにアプリケーションの全ての状態をもつという設計も可能ですが、それはやりすぎです。

あるコンポーネントでしか使わないようなデータは、ストアを使わず data に持たせたほうが、よいです。

Vuexに管理させたい場合の判断材料としては、「アプリケーション全体に関わるデータ」はストアに持たせるというのが、推奨されている使い方のようです。

ストアに持たせたほうがよい

  • ログイン情報
  • 共通のheaderなどでバッジで表示する、アプリケーションからのNotification通知

コンポーネントのdata

ゲッター

ストア版computed(算出プロパティ)という感じのようです。

通常の算出プロパティ同様、キャッシュが可能のようです。

getters: {
    aaa: (state) => state.sum * state.sum,
    
    bbb: (state, getters) => state.sum * getters.aaa
}

ミューテーション

ステートを更新するために使用されます。

ReduxでいうReducerっぽい感じかと思いますが、Reducderと違うのはstoreが編集可能というところでしょうか?

Reducerは既存の状態と、今回やりたい変更をマージして、新しい状態を作るという感じなので、読み取り専用だったような気がしてます。

いいか悪いかは別として、個人的にはReduxよりわかりやすくはあります。

ミューテーションは、直接呼び出すことはできません。

store.commit('ミューテンション名') という感じで呼び出します。

store.commit実行時に、オブジェクトで第二引数を渡すと、ミューテーションの第二引数 payloadとして渡すことができます。

mutations: {
    mu_01: (state, payload) {
        state.amount = state.amount + payload.amount
    }
}


store.commit('mu_01', { amount: 10 })

そこまで難しい感じではないですね。

注意点としては、ミューテーション内で非同期通信処理を含めないほうがよいということです。

非同期通信処理を行いたい場合は、次のアクションで行うべきです。

アクション

非同期処理や外部のAPIとの連携を行い、最終的にステートを更新するためのミューテーションを呼び出すために使用します。

アクションもミューテーションと同じく、直接呼び出せません。

store.dispatch('アクション名') という形で呼び出します。

actionのメソッドの引数は1つで、コンテキストという引数が渡されてきます。

  • state: 現在のステート
  • getters: 定義されているゲッター
  • dispatch: 他のアクションを実行するメソッド
  • commit: ミューテーションを実行するメソッド

このブロックの最後に、アクションでajaxを使用してデータをとってくるような擬似的コードが記載されています。

目新しいところはありませんでしたが、 非同期通信のコールバック時に、引数のコンテキストのcommitを使用して、ミューテーションを実行して、ストアを変更しています。

7.5 タスク管理アプリケーションの状態管理

こちらは例題として、簡単なタスク管理アプリケーションを開発して、Vuexの使用方法を学びます。

こちらは写経しました。

シンプルな機能だったので、「そうなってしまった」のかもしれませんが、storeに処理を委譲しているようなロジックでした。

なるほどと思ったのは、算出プロパティの追加方でした。

なんとなく計算結果を返すというイメージだったのですが、storeの情報を返すようにするという使い方は、コードも読みやすいし、わかりやすかったです。

  ## component

  computed: {
    tasks () {
      return this.$store.getters.filteredTasks
    },

    labels () {
      return this.$store.state.labels
    },

    filter () {
      return this.$store.state.filter
    }
  },
  
  ## store
  
  state: {
    tasks: [
      {
        id: 1,
        name: '牛乳を買う',
        labelIds: [1, 2],
        done: false
      },
      {
        id: 2,
        name: 'Vue.jsの本を買う',
        labelIds: [1, 3],
        done: true
      }
    ],

    labels: [
      {
        id: 1,
        text: '買い物'
      },
      {
        id: 2,
        text: '食料'
      },
      {
        id: 3,
        text: '本'
      }
    ],

7.6 ストアのモジュール分割

先程から出てきているストアの分割の話です。

モジュールという単位で分割できます。

const AAA = {
    state: {
    },
    
    getters: {
    },
    
    mutations: {
    },
    
    actions: {
    },
    
    modules: {
      childModule: {
        // モジュールの入れ子もできる
      }
    }
}

const store = new Vuex.Store({
    modules: {
        AAA
    }
})

7.7 VuexストアとVueコンポーネント間の通信

コンポーネントからストアへのアクセス方法が記載されています。

this.$store でアクセスすることができます。

また別の方法として、ヘルパー関数でのアクセスも紹介されています。

mapState, mapGetters, mapMutations, mapActionsです。

具体的な使用例が本書に記載されていました。

こちらも写経いたしました。

7.8 VuexとVue Routerの連携

vuex-router-syncでこちらの問題は解決します。

import { sync } from 'vuex-router-sync'

sync(store, router)

// syncしたとことでstore.state.route以下にルーティングのデータが入る。
console.log(store.state.route)

終わりに

大型の写経部分があったので、ガッツリコードを書きました。

また、今回は写経が多い章だったので、そのままガッツリコードを乗せるわけにも行かず、書くのに苦労しました。

ただ、ガッツリ写経できたおかげで基本的な動きはつかめたと思います。

写経したコードもとてもわかり易かったので、まだ未読の方はぜひ買ってみてください。

nuxtなどと連携した際また違った動きになるのかどうか、そのあたりももう少し勉強しようと思います。

おしまい。