書籍概要

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

著者
発売日
更新日

概要

Vue.jsを初歩から実践まで徹底的に解説。使いやすくかつ,プロダクションでも活躍するVue.jsをVue.jsコントリビューターの著者らが解説する一番わかりやすい入門書です。小規模な適用例やjQueryからの移行サンプルに加え,大規模開発を想定したアプリケーション開発も体験できます。Vue.jsはGitHubで2017年最も人気のあったJavaScriptフレームワークに選ばれるなど大注目の技術です。

こんな方におすすめ

  • Vue.jsに興味のあるWebエンジニア
  • Vue.jsを本番で使いたいが課題があるエンジニア
  • Vue.jsを動かしてみたいWebデザイナー,コーダー

目次

1. プログレッシブフレームワークVue.js

  • 1.1 現代のWebフロントエンド開発の複雑化
    • 1.1.1 Webの誕生とWebベースシステムへの発展
    • 1.1.2 Ajaxの登場
    • 1.1.3 HTML5,Node.js,ES2015,React以降の世界
    • Column AltJSの登場
    • 1.1.4 現在の課題とVue.js
  • 1.2 Vue.jsの特徴
    • 1.2.1 学習コストが低い
    • 1.2.2 コンポーネント指向によるUIの構造化
    • 1.2.3 リアクティブなデータバインディング
  • 1.3 Vue.jsの設計思想
    • 1.3.1 フレームワークの複雑性
    • 1.3.2 要求の変化に追随できるフレームワーク
  • 1.4 プログレッシブフレームワークの解決する段階的な領域
    • 1.4.1 宣言的レンダリング(Declarative Rendering)
    • 1.4.2 コンポーネントシステム(Component System)
    • 1.4.3 クライアントサイドルーティング(Client-side Routing)
    • 1.4.4 大規模向け状態管理(Large-scale State Management)
    • 1.4.5 ビルドシステム(Build System)
    • 1.4.6 クライアントサーバーデータ永続化(Client-server Data Persistence)
  • 1.5 Vue.jsを支える技術
    • 1.5.1 コンポーネントシステム
    • 1.5.2 リアクティブシステム
    • Column リアクティブシステムの内側
    • 1.5.3 レンダリングシステム
    • Column Vue.jsの仮想DOMの処理の流れ
  • 1.6 Vue.jsのエコシステム
  • 1.7 Vue.jsのはじめの一歩
    • Column JSFiddleで実践
    • Column Vue.jsのドキュメンテーション
    • Column Vue.jsコミュニティ
    • Column Vue.jsの対応ブラウザ

2. Vue.jsの基本

  • 2.1 Vue.jsでUIを構築する際の考え方
    • 2.1.1 旧来のUI構築の問題点
    • 2.1.2 Vue.jsのUI構築
  • 2.2 Vue.jsの導入
    • Column Vue.jsの高度な環境構築
  • 2.3 Vueオブジェクト
    • 2.3.1 コンストラクタ
    • Column MVVMパターン
    • 2.3.2 コンポーネント
  • 2.4 Vueインスタンスのマウント
    • 2.4.1 Vueインスタンスの適用(el)
    • 2.4.2 メソッドによるマウント($mountメソッド)
    • Column Vue.jsを既存アプリケーションに導入する
  • 2.5 UIのデータ定義 (data)
    • 2.5.1 Vueインスタンスの確認
    • 2.5.2 データの変更を検知する
  • 2.6 テンプレート構文
    • 2.6.1 テキストへの展開
    • 2.6.2 属性値の展開
    • 2.6.3 JavaScript式の展開
  • 2.7 フィルタ(filters)
    • Column フィルタの連結
  • 2.8 算出プロパティ(computed)
    • 2.8.1 thisによる参照
    • 2.8.2 サンプルアプリケーションでの実装
  • 2.9 ディレクティブ
    • 2.9.1 条件付きレンダリング(v-if/v-show)
    • 2.9.2 クラスとスタイルのバインディング
    • 2.9.3 リストレンダリング(v-for)
    • Column リストレンダリングパフォーマンス
    • 2.9.4 イベントハンドリング(v-on)
    • 2.9.5 フォーム入力バインディング(v-model)
    • Column 修飾子による動作の変更
  • 2.10 ライフサイクルフック
    • 2.10.1 ライフサイクルフック一覧とフロー
    • 2.10.2 createdフック
    • 2.10.3 mountedフック
    • 2.10.4 beforeDestroyフック
  • 2.11 メソッド(methods)
    • 2.11.1 イベントオブジェクト
    • Column 算出プロパティのキャッシュ機構
    • 2.11.2 サンプルでのメソッドの呼び出し

3. コンポーネントの基礎

  • 3.1 コンポーネントとは何か
    • 3.1.1 全てはUIコンポーネントから構成される
    • 3.1.2 コンポーネント化のメリットと注意点
    • 3.1.3 Vue.jsのコンポーネントシステム
    • Column Vue.jsのコンポーネントとWeb Components
  • 3.2 Vueコンポーネントの定義
    • 3.2.1 グローバルコンポーネントの定義
    • 3.2.2 コンストラクタベースの定義
    • Column ReactのRender Props
    • 3.2.3 ローカルコンポーネントの定義
    • 3.2.4 テンプレートを構築するその他の手段
    • Column コンポーネントの命名規則について
    • 3.2.5 コンポーネントのライフサイクル
    • 3.2.6 コンポーネントのデータ
    • Column オブジェクトを指定した場合の警告
  • 3.3 コンポーネント間の通信
    • 3.3.1 親コンポーネントから子コンポーネントへデータの伝播
    • 3.3.2 子コンポーネントから親コンポーネントへの通信
    • Column propsとイベントを用いない親子間のやりとり
    • Column 親子以外のコンポーネントでデータをやりとりする
    • Column 子から親のネイティブDOMイベントを取得したい場合 ― .native修飾子
    • Column propsの値に関して双方向バインディングを実現したい場合 ― .sync修飾子
  • 3.4 コンポーネントの設計
    • 3.4.1 コンポーネントの分割方針
    • 3.4.2 コンポーネント自体の設計
    • Column Atomic Design
    • 3.4.3 スロットコンテンツを活かしたヘッダーコンポーネントの作成
    • 3.4.4 ログインフォームコンポーネントの作成
    • Column コンポーネント単位のテスト

4. Vue Routerを活用したアプリケーション開発

  • 4.1 Vue Routerによるシングルページアプリケーション
    • 4.1.1 シングルページアプリケーションとルーティング
    • 4.1.2 Vue Routerとは
  • 4.2 ルーティングの基礎
    • 4.2.1 ルーターのインストール
    • 4.2.2 ルーティング設計
  • 4.3 実践的なルーティングのための機能
    • 4.3.1 URLパラメーターの扱いとパターンマッチング
    • 4.3.2 名前付きルート
    • 4.3.3 router.pushを使った遷移
    • 4.3.4 フック関数
  • 4.4 サンプルアプリケーションの実装
    • 4.4.1 リストページの実装
    • 4.4.2 APIによるデータ通信
    • 4.4.3 詳細ページの実装
    • 4.4.4 ユーザー登録ページの実装
    • 4.4.5 ログイン・ログアウトの実装
    • 4.4.6 サンプルアプリケーションの全体像
  • 4.5 Vue Routerの高度な機能
    • 4.5.1 RouterインスタンスとRouteオブジェクト
    • 4.5.2 ネストしたルーティング
    • 4.5.3 リダイレクト・エイリアス
    • 4.5.4 履歴の管理
    • Column Vue Routerを使った大規模なアプリケーションの実装
    • Column Vue RouterとReact Router

5. Vue.jsの高度な機能

  • 5.1 トランジションアニメーション
    • 5.1.1 transitionラッパーコンポーネント
    • 5.1.2 トランジションクラス
    • 5.1.3 fadeトランジションの実装
    • Column Vue Routerのトランジション
    • Column カスタムトランジションクラス
    • 5.1.4 JavaScriptフック
  • 5.2 スロット
    • 5.2.1 単一スロット
    • 5.2.2 名前付きスロット
    • 5.2.3 スロットのスコープ
  • 5.3 カスタムディレクティブ
    • Column コンポーネントやミックスインとの違い
    • 5.3.1 作成するカスタムディレクティブの定義
    • 5.3.2 ディレクティブ定義オブジェクト
    • 5.3.3 フック関数の引数
    • 5.3.4 image-fallbackディレクティブの機能追加
    • Column DOM操作を行うライブラリをラップする
  • 5.4 描画関数
    • 5.4.1 描画関数を用いないと書きづらい例
    • 5.4.2 描画関数による効率化
    • 5.4.3 createElement関数
    • Column h関数
    • Column JSX
  • 5.5 ミックスイン
    • 5.5.1 ミックスインで機能を再利用する
    • 5.5.2 グローバルミックスイン
    • Column ミックスインの命名規則

6. 単一ファイルコンポーネントによる開発

  • 6.1 ツールのインストール
    • 6.1.1 Vue CLI
  • 6.2 単一ファイルコンポーネントとは
  • 6.3 単一ファイルコンポーネントの仕様
    • 6.3.1 <template>ブロック
    • 6.3.2 <script>ブロック
    • 6.3.3 <style>ブロック
  • 6.4 単一ファイルコンポーネントのビルド
  • 6.5 単一ファイルコンポーネントの動作を体験する
    • 6.5.1 動作を押さえる
  • 6.6 単一ファイルコンポーネントの機能
    • 6.6.1 外部ファイルのインポート
    • 6.6.2 スコープ付きCSS
    • Column スコープ付きCSSのメリット
    • 6.6.3 CSSモジュール
    • 6.6.4 他言語実装のサポート
    • Column カスタムブロック
    • Column カスタムブロックの定義

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

  • 7.1 複雑な状態管理
  • 7.2 データフローの設計
    • 7.2.1 信頼できる唯一の情報源(Single Source of Truth)
    • 7.2.2 「状態の取得・更新」のカプセル化
    • 7.2.3 単方向データフロー
  • 7.3 Vuexによる状態管理
    • 7.3.1 Vuexのインストール
  • 7.4 Vuexのコンセプト
    • 7.4.1 ストア
    • 7.4.2 ステート
    • 7.4.3 ゲッター
    • 7.4.4 ミューテーション
    • 7.4.5 アクション
  • 7.5 タスク管理アプリケーションの状態管理
    • 7.5.1 アプリケーションの仕様と準備
    • 7.5.2 タスクの一覧表示
    • 7.5.3 タスクの新規作成と完了
    • 7.5.4 ラベル機能の実装
    • 7.5.5 ラベルのフィルタリング
    • 7.5.6 ローカルストレージへの保存と復元
    • 7.5.7 Vuexによるアプリケーションの考察
  • 7.6 ストアのモジュール分割
    • 7.6.1 namespacedオプションによる名前空間
  • 7.7 VuexストアとVueコンポーネント間の通信
    • 7.7.1 コンポーネントからストアにアクセスする
    • 7.7.2 ストアにアクセスするコンポーネントを必要最小限にする
  • 7.8 VuexとVue Routerの連携

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

  • 8.1 Vue.jsのプロジェクト構築の特徴
    • 8.1.1 Vue.jsで本格的な開発をするための心構え
  • 8.2 本章で作成するアプリケーション
    • 8.2.1 アプリケーション仕様概要
    • 8.2.2 アプリケーションアーキテクチャ
    • Column バックエンドの設計
  • 8.3 アプリケーションの開発環境構築
    • 8.3.1 開発環境構築をサポートするVue CLI
    • 8.3.2 JavaScriptの環境構築とVue CLI
    • Column vue init について
  • 8.4 Vue CLIによる開発環境の構築
    • 8.4.1 アプリケーションプロジェクトの作成
    • 8.4.2 プロジェクト構造
    • 8.4.3 タスクコマンド
    • 8.4.4 アプリケーションの起動確認
    • 8.4.5 アプリケーションの環境変数
  • 8.5 アプリケーションのビルド
    • 8.5.1 アセット処理
    • 8.5.2 リントツール
  • 8.6 テスト環境
    • 8.6.1 単体テスト
    • 8.6.2 E2Eテスト
  • 8.7 フロントエンド・バックエンド連携
    • 8.7.1 APIのプロキシ
    • 8.7.2 バックエンドとのインテグレーション
  • 8.8 さらなる開発環境の強化
    • 8.8.1 Vue.jsコーディング環境の構築
    • 8.8.2 Vue.js公式ESLintプラグインの導入
    • 8.8.3 デバッグとプロファイリングの環境構築
    • 8.8.4 バックエンドAPIサーバーの環境構築
    • 8.8.5 状態管理ライブラリの導入
    • 8.8.6 HTTPクライアントライブラリの導入
    • 8.8.7 単体テストユーティリティの導入
    • 8.8.8 E2Eテストのコマンド登録

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

  • 9.1 コンポーネント設計
    • 9.1.1 Atomic Designによるコンポーネントの抽出
    • 9.1.2 Atoms
    • 9.1.3 Molecules
    • 9.1.4 Organisms
    • 9.1.5 Templates
  • 9.2 単一ファイルコンポーネント化
    • 9.2.1 ディレクトリの構造化と各ファイルの配置
    • 9.2.2 コンポーネントのAPI
    • 9.2.3 KbnButtonコンポーネントのAPI
  • 9.3 状態モデリングとデータフローの設計
    • 9.3.1 状態モデリング
    • 9.3.2 データフロー
    • 9.3.3 データフロー周りの雛形コードのセットアップ
    • 9.3.4 アクションの雛形
  • 9.4 ルーティング設計
    • 9.4.1 ルートフロー
    • 9.4.2 ルート定義

10. 中規模・大規模向けのアプリケーション開発③ 実装

  • 10.1 開発方針の整理
    • 10.1.1 アプリケーションの実装に入る前に
  • 10.2 コンポーネントの実装
    • 10.2.1 KbnButtonコンポーネント
    • 10.2.2 KbnLoginFormコンポーネント
    • 10.2.3 KbnLoginViewコンポーネント
  • 10.3 データフローの実装
    • 10.3.1 loginアクションハンドラ
    • 10.3.2 AUTH_LOGINミューテーションハンドラ
    • 10.3.3 Auth APIモジュール
  • 10.4 ルーティングの実装
    • 10.4.1 beforeEachガードフックを活用したナビゲーションガード
  • 10.5 開発サーバーとデバッグ
    • 10.5.1 開発サーバーによる開発
    • 10.5.2 Vue DevToolsによるデバッグ
  • 10.6 E2Eテスト
    • 10.6.1 E2Eテストの実装
    • 10.6.2 テストの実行
  • 10.7 アプリケーションのエラーハンドリング
    • 10.7.1 子コンポーネントのエラーハンドリング
    • 10.7.2 グローバルなエラーハンドリング
  • 10.8 ビルドとデプロイ
    • 10.8.1 アプリケーションのビルド
    • 10.8.2 アプリケーションのデプロイ
    • Column Vue.jsのバックエンド
  • 10.9 パフォーマンス測定・改善
    • 10.9.1 パフォーマンス測定の設定方法
    • 10.9.2 測定できる処理
    • 10.9.3 レンダリングパフォーマンスの向上
    • Column Vue CLIの対話的な選択時の注意点
    • Column テンプレートコンパイラのオプションを利用する

Appendix A jQueryからの移行

  • A.1 移行の判断
  • A.2 jQueryで実装していた機能のVue.jsによる実装
    • A.2.1 イベントリスナー
    • A.2.2 表示の切り替え
    • A.2.3 要素の挿入・削除
    • A.2.4 属性値の変更
    • A.2.5 クラスの変更
    • A.2.6 スタイルの変更
    • A.2.7 フォーム(ユーザー入力)

Appendix B 開発ツール

  • B.1 Storybook
    • B.1.1 開発プロジェクトに導入する
    • B.1.2 Storybookを動作させる
    • B.1.3 ストーリーを実装する
    • B.1.4 Storybookを公開する
  • B.2 静的型付き言語
    • B.2.1 TypeScript
    • B.2.2 TypeScriptの記述例
    • B.2.3 セットアップ
    • Column TypeScriptコンパイラ
    • B.2.4 コンポーネントの実装
    • Column 単一ファイルコンポーネント用の設定
    • B.2.5 エディタ
    • B.2.6 ライブラリの型定義
    • Column TypeScriptの型定義がないとき
    • Column Vue.jsとFlow

Appendix C Nuxt.js

  • C.1 Nuxt.jsとは
  • C.2 Nuxt.jsの特徴
    • C.2.1 サーバーサイドレンダリングのサポート
    • Column サーバーサイドレンダリング環境の構築
    • Column サーバーサイドレンダリングの必要性
    • C.2.2 すぐに開発着手できる開発環境と拡張性の提供
    • C.2.3 静的なHTMLファイル生成のサポート
  • C.3 Nuxt.jsをはじめる
  • C.4 Nuxt.jsで静的サイトを作成する
    • C.4.1 画面仕様
    • C.4.2 ルーティングを追加する
    • C.4.3 グローバルナビゲーションのコンポーネントを追加する
    • C.4.4 レイアウトにグローバルナビゲーションを追加する
    • C.4.5 開発サーバーで動作確認する
    • C.4.6 静的なHTMLファイルにビルドする
    • Column Nuxt.jsにおけるサーバーサイドレンダリング

サポート

ダウンロード

(2020年8月12日更新)

以下のファイルをダウンロードできます。
圧縮ファイルをダウンロードして,適宜展開してご利用ください。
2019年9月9日,動作しなかったコードを修正しています。ダウンロードしなおしてください。

ダウンロード
sample20200811.zip

正誤表

本書の以下の部分に誤りがありました。ここに訂正するとともに,ご迷惑をおかけしたことを深くお詫び申し上げます。

(2020年8月12日最終更新)

P.96 3.3.1のコンポーネントの表記例

誤

<div id=app>

正

<div id="app">

(以下2019年10月9日更新)

P.135 # 4.4.5のグローバルメニューにログアウトメニュー・ログインメニューを追加したあとの解説

本来はグローバルメニューにログアウト・ログインメニュー実装後に下記のようにログイン関連の説明を追加すべきでした。

正

上記グローバルメニューのHTML内で認証モジュールAuthを利用するために、Vueインスタンス生成時のdataプロパティにAuthを指定しましょう。


var app = new Vue({
  data: {
    Auth: Auth
  },
  router: router
}).$mount('#app')

(以下2019年9月10日更新)

P.107 # 3.4.3のコンテンツを埋め込まずにslotを使った場合の画像例

画像が誤っていました。文言は同一ですがスタイルが一部異なります。

P.107 # 3.4.3のコンテンツを埋め込んだ場合の画像例

画像が誤っていました。「りんご、イチゴ」と表記されるべき部分が「いちご、りんご」となっていました。

P.167 # 5.2.3の「スコープ付きスロット」の例のHTML側の表記

slot-scopeを使わないもの,使うものそれぞれ動作しますが,:keyの指定が抜けていました。



<li slot-scope="slotProps" v-if="slotProps.todo.isCompleted" :key="slotProps.todo.id">



<li slot-scope="{ todo }" v-if="todo.isCompleted" :key="todo.id">

P.221 # 6.6.3の「名前付きスタイル識別子の算出プロパティ」の実行

vue serveに指定するファイル名が誤っていました。正しくはform.vueを開く箇所でした。


$ editor form.vue
$ vue serve form.vue --open

P.196 # 5.5.2のコード,authに関する記述

初出の$optionsに対する説明のコメントが不足していました。

誤

var auth = this.$options.auth

正

var auth = this.$options.auth // $optionsでVueインスタンス生成時のオプションを参照できます

P.354〜P.355 # 10.2.1 kbnButtonコンポーネントの単体テストコード(disabledプロパティの値がfalseのテストコード)

本来はテストコードでpropsDataを指定しなければいけない箇所で指定していませんでした。直前のテストコードでtrueにしているのを参照してください。

誤

  describe('false', () => {
    it('disabled属性が付与されていないこと', () => {
      const button = mount(KbnButton)
      expect(button.attributes().disabled).to.be.an('undefined')
    })
  })

正

  describe('false', () => {
    it('disabled属性が付与されていないこと', () => {
      const button = mount(KbnButton, {
        propsData: { disabled: false }
      })
      expect(button.attributes().disabled).to.be.an('undefined')
    })
  })

(以下2019年5月13日更新)

P.69 # 2.10.1のライフサイクルフック一覧表

表中の表記が誤っていました。

誤 detroyed
正 destroyed

(以下2019年3月22日更新)

P.96 # 3.3.1のコンポーネントの書式の誤り

defaultとすべき箇所が,defalutと誤っていました。
正しくは以下の通りです。

Vue.component(コンポーネント名,{
  props: {
    親から受け取る属性名:{
      type: StringやObjectなどのデータ型,
      default: デフォルト値,
      required: 必須かどうかの真偽値,
      validator: バリデーション用の関数
    }
  }
  // ...template内で「親から受け取る属性」が使える
})

P.193 # 5.5.1の説明文

誤 Consoleの出力から、ミックスイン→コンポーネントの順番フック関数が呼ばれていることが分かります。
正 Consoleの出力から、ミックスイン→コンポーネントの順番でフック関数が呼ばれていることが分かります。

(以下2019年2月18日更新)

P.107 # 3.4.3の最後のJSFiddleのURL

本来挿入されるべき,Vue.jsの読み込みが行われていませんでした。

誤

https://jsfiddle.net/bha18soe/

正

https://jsfiddle.net/upd9843j/ 

P.182,P.183 # 5.4.3のデータオブジェクト中のソースコード

P.182の下段からP.183中段にかけての,my-buttonのコードに不足があり動作しませんでした。正しくは下記のコードです。

正

new Vue({
  el: '#app',
  render: function (createElement) {
    return createElement('my-button', {
      attrs: {
        href: 'https://vuejs.org/'
      },
      props: {
        tag: 'a'
      }
    }, 'anchor')
  },
  components: {
    MyButton: MyButton
  }
})



正

new Vue({
  el: '#app',
  render: function (createElement) {
    return createElement(MyButton, {
      attrs: {
        href: 'https://vuejs.org/'
      },
      props: {
        tag: 'a'
      }
    }, 'anchor')
  }
})

(以下,2019年2月4日更新)

P.200 # 6.1.1冒頭のVue CLIに関する解説のページ

誤 Vue CLIは、Vue.js向けのアプリケーション開発環境をセットアップなどの機能を提供する公式のコマンドラインツールです。
正 Vue CLIは、Vue.js向けのアプリケーション開発環境セットアップなどの機能を提供する公式のコマンドラインツールです。

P.331 # 9.2.1のディレクトリ作成

誤

$ mkdir -p src/ components/{ atoms, molecules, organsms, templates}

正

$ mkdir -p src/ components/{ atoms, molecules, organisms, templates}

P.346 # 9.4.1最初の構成図

図中の番号表記が誤っていました。正しくは下記です。

(以下2018年11月14日更新)


(以下2018年11月14日更新)

P.123 # 4.4の最初のコードブロック

誤

<!-- router-link による ナビゲーション 定義 -->>

正

<!-- router-link による ナビゲーション 定義 -->

P.125 # 4.4.2の説明文

誤 UserListコンポーネントのテンプレートとJavaScriptを回収していきます。
正 UserListコンポーネントのテンプレートとJavaScriptを改修していきます。

P.215 6章の「コラム スコープ付きCSSのメリット」のコードのbar.vue

コードが誤っていました。正しくは下記のコードです。


<template>
  <div class="bar">
    <h1 class="header">Barコンポーネント</h1>
    <p>これはBarコンポーネントです。</p>
    <foo/> <!-- Fooコンポーネントの利用。scriptブロックも要注目 -->
  </div>
</template>

<script>
import Foo from './foo'
export default { // FooコンポーネントをBarコンポーネントに登録
  components: {
    Foo
  }
}
</script>

<style scoped>
.bar {
  border: 1px solid red;
  margin: 4px;
  padding: 4px;
}
.header { font-size: 125%; }
</style>

P.280~281 # 7.6.1 の最後のコードブロックのコード例

actionsとすべき個所がactionになっていました。正しくは下記のコードです。


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

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    // fooモジュール
    foo: {
      state: {
        value: 123
      },

      actions: {
        log (ctx) {
          console.log('モジュールfooのステート', ctx.state)
        }
      }
    },

    // barモジュール
    bar: {
      state: {
        message: 'Hello!'
      },

      actions: {
        log (ctx) {
          console.log('モジュールbarのステート', ctx.state)
        }
      }
    }
  }
})

// logアクションを呼び出す
// fooモジュール内のステートと、barモジュール内のステートが出力される
store.dispatch('log')

P.358 # 10.2.2の
test/unit/specs/components/molecules/kbnLoginForm.spec.js中のdescribeに与える文言

メールアドレス形式のフォーマットを検証する部分で,itの第一引数に与える説明が誤っていました。

誤

describe('メールアドレス形式のフォーマット', () => {
    it('validation.email.requiredがvalidであること', () => {

正

describe('メールアドレス形式のフォーマット', () => {
    it('validation.email.formatがvalidであること', () => {


P.371 # 10.3.1のコード中のコメント

誤

 // commitが呼ばれていなかチェック

正

 // commitが呼ばれていないかチェック


(以下2018年10月10日更新)

P.299  8.4.1のvue init時の引数の文字列

誤 $ vue init webpack kandan-app
正 $ vue init webpack kanban-app

(以下2018年10月3日更新)

P.305 8.5冒頭の箇条書き

誤・複数のHTMLテンプレート
・CSSやSassなどのスタイルシート
・JavaScriptファイルによって
正 ・HTMLテンプレート
・CSSやSassなどのスタイルシート
・JavaScript

P.308の脚注部を除く最下行 8.6.1のKarmaのインストールに関する説明

文章が途中で抜けていました。

誤 Karma公式でサポートする
正 Karma公式でサポートするKarmaランチャ

(以下2018年9月21日更新)

P.2 1章のプロジェクトに関する説明

誤 プロジェクトして開発を行っています。
正 プロジェクトとして開発を行っています。

P.10 1.2.1のコード例に関する説明

誤 まだ文法事項を解説してないので、
正 まだ文法事項を解説していないので、

P.11の5行目 1.2.1の説明

誤 Vue.jsは先に上げた現代のWebフロントエンド開発の
正 Vue.jsは先に挙げた現代のWebフロントエンド開発の

P.18 1.5.1の単一ファイルコンポーネントのコード例

templateの閉じタグが誤っていました。

誤


<template>
  <p>{{message}}!</p>
<template>
<script>
export default = {
  data () {
    return {
      message: 'こんにちは'
    }
  }
}
</script>
<style scoped>
p {
  color: red;
}
</style>


正


<template>
  <p>{{message}}!</p>
</template>
<script>
export default = {
  data () {
    return {
      message: 'こんにちは'
    }
  }
}
</script>
<style scoped>
p {
  color: red;
}
</style>


P.22 1.6の冒頭の説明

誤 ユーザーのWebアプリケーションを開発をサポートするために
正 ユーザーのWebアプリケーション開発をサポートするために

P.23 1.6のVue Curatedの説明

誤 Vue.jsコアチームが激選したプラグイン、
正 Vue.jsコアチームが厳選したプラグイン、

P.34 2.3 Vueオブジェクトの説明文

誤 基本機能を紹介してきます。
正 基本機能を紹介していきます。

P.47 2.7の実行結果の画面

実行結果画面が誤っていました。正しくは下記画面です。画像をクリックすると大きく表示できます。

P.55 2.9.2のstyleの記述例を説明した文中のコード表記例

誤

styleはセミコロン("collor: tomato; background: yellow")で

正

styleはセミコロン("color: tomato;; background: yellow")で

P.71 2.10.4のコード例中のコメント

誤

// データに参照できる

正

// データを参照できる

P.73 コラム 算出プロパティのキャッシュ機構の最初の説明

誤 ここで説明したメソッドと先程の算出プロパティは、いずれも関数の形と取るという点では同じで、
正 ここで説明したメソッドと先程の算出プロパティは、いずれも関数の形を取るという点では同じで、

P.85 3.2.1 グローバルコンポーネントの定義内のオプション表のfilters行

誤 データを文字列と整形する
正 データを文字列に整形する

P.96 3.3.1のフルーツの名前をリストするコンポーネント中のコメント

誤

<!-- v-forで繰り返した各furitをprops(fruits-item)に与えている --> 

正

<!-- v-forで繰り返した各fruitをprops(fruits-item)に与えている --> 

P.104 コラム Atomic DesignのOrganisms中の例の説明

誤 ログインフォームやコメントフォームなナビゲーションバーなど。
正 ログインフォームやコメントフォーム、ナビゲーションバーなど。

P.108 3.4.4 箇条書きの項目名

誤 ユーザーID入力欄
正 ログインID入力欄

P.118の3行目 4.2.2の「HTML側の指定とページ遷移の実行」のrouter-viewなどの説明箇所

誤 〜部分にレンダリングされます。ページを開いてからページ遷移が
正 〜部分にレンダリングされます。しかし、ページを開いてからページ遷移が

P.123 4.4の冒頭の解説

誤 例として、ユーザー情報登録・閲覧が可能なアプリケーション用います。
正 例として、ユーザー情報登録・閲覧が可能なアプリケーションを用います。

P.123 4章の脚注7

誤 ES2015以降でプログラムを作成したい場合もWebpackの利用はほぼ必須です。
正 ES2015以降でプログラムを作成したい場合もwebpackの利用はほぼ必須です。

P.124 4.4リスト中のライブラリの読み込み部分

動作はしますがバージョンが古いものでした。

誤


<script src="https://unpkg.com/vue@2.4.2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router@2.7.0/dist/vue-router.min.js"></script>


正


<script src="https://unpkg.com/vue@2.5.17"></script>
<script src="https://unpkg.com/vue-router@3.0.1"></script>


P.136 4.4.6のリスト中のvue-routerのバージョン指定

誤 <script src="https://unpkg.com/vue-router@3.1.0"></script>
正 <script src="https://unpkg.com/vue-router@3.0.1"></script>

P.147 「コラムVue Routerを使った大規模なアプリケーションの実装」の表記

誤 propを使ったデータの受け渡しチェーン
正 propsを使ったデータの受け渡しチェーン

P.151 5.1.3の記述

誤 実際にコードと見ていきます。
正 実際にコードを見ていきます。

P.160 5.1.4最後のアニメーション関連の文章

誤 Velocity.js,jQueryのアニメーション機能、
正 Velocity.js、jQueryのアニメーション機能、

P.161 5.2のスロットの説明

誤 プロパティでテキストを渡して表示されても
正 プロパティでテキストを渡して表示しても

P.168 5.3のビルトインのディレクティブとの比較解説

誤 Vue.jsのアプリケーションを実装する上で、ビルドインの
正 Vue.jsのアプリケーションを実装する上で、ビルトインの

P.168 5.3のローカルディレクティブの利用例

誤 ブログエントリの要素付けのUIなどです。
正 ブログエントリのタグ付けのUIなどです。

P.170 5.3.1の画像の説明の表記

誤 すると以下のようにnoimageの画像が
正 すると以下のようにno imageの画像が

P.172 5.3.3の「updateフックによる値の変更の検知」内のoldValueプロパティの説明

誤 そこで、bindingのvalue、oldValueプロパティの値を比較して...
正 そこで、bindingのvalue、updateとcomponentUpdatedフックで利用できる変更前の値oldValueプロパティを比較して...

P.174 5.3.4のコード中のbindの表記

本来「:」とすべき個所が「!」になっていました。

誤

bind! function (el, binding) {

正

bind: function (el, binding) {

P.175 5.3.4のコード中のupdateとdataの表記

本来「:」とすべき個所が「!」になっていました。

誤

update! function (el, binding) {

正

update: function (el, binding) {

誤

data! function() {

正

data: function() {

P.175 5.3.4のnoImageURLプロパティに関する記述

誤 文字列をセットして、属性値と指定します。
正 文字列をセットして、属性値を指定します。

P.176 5.3.4の何も表示されない状態に関する記述

誤 no_image画像も何も表示されなくなるはずです。
正 no image画像も何も表示されなくなるはずです。

P.182 5.4.3の「データオブジェクト」コード中のrenderの表記

誤

render! function (createElement) {

正

render: function (createElement) {

P.192 5.5.1のmixinsプロパティの説明

誤 コンポーネントオプジョンのmixins
正 コンポーネントオプションのmixins

P.194 5.5.1のオプションに関する記述

誤 methodsやcomponents,directives等の
正 methodsやcomponents、directives等の

P.194 5.5.1のシェアメソッドに関する記述

誤 コンポーネントで同名のシェアというメソッドを
正 コンポーネントで同名のshareというメソッドを

P.197 5.5.2の最後にJSONを文字列に変更する際のコードの誤り

誤

JSON.strinfigy({name: 'Evan You'})

正

JSON.stringify({name: 'Evan You'})

P.210,p.211 6.6.2の「複数の<style>ブロックの定義」における参照先

参照先が誤っていました。正しくは6.6.2以降で利用するコラムを参照します。

誤 先に利用した単一ファイルコンポーネントのFooコンポーネントとRootコンポーネントを以下のように変更します。
正 「コラム スコープ付きCSSのメリット(後述)」の単一ファイルコンポーネントfoo.vueとroot.vueを以下のように変更し、bar.vueをそのまま利用します。適宜サンプルを参照してください。
誤 先程と同じ画面がWebブラウザに
正 コラムと同じ画面がWebブラウザに

P.214 6.6.2の「子コンポーネントのルート要素におけるスタイルの注意事項」の表示例画像のキャプション

誤 socped属性によるカプセル化が
正 scoped属性によるカプセル化が

P.215 6章の「コラム スコープ付きCSSのメリット」のコード

コラム内のfoo.vue,root.vueのコードがtemplate部分のみ抜粋する形になっていたため全体を掲載いたします。

foo.vue


<template>
  <div class="foo">
    <h1 class="header">Fooコンポーネント</h1> <p>これはFooコンポーネントです。</p>
  </div>
</template>
<style scoped>
.foo { border: solid 1px green; margin: 4px; padding: 4px; }
.header { font-size: 150%; }
</style>

root.vue


<template>
  <div id="root">
    <h1 class="header">Rootコンポーネント</h1> <p>これはRootコンポーネントです。</p>
    <foo/> <bar/>
  </div>
</template>
<script>
import Foo from './foo'
import Bar from './bar'
export default {
  components: { Foo, Bar }
}
</script>
<style>
#root { border: solid 1px blue; margin: 4px; padding: 4px; }
.header { font-size: 200%; }
p { text-decoration: underline; }
</style>

P.219 6.6.3の$styleに関する記述

誤 Vue.jsのクラスに対して使用可能なのオブジェクト
正 Vue.jsのクラスに対して使用可能なオブジェクト

P.225 6.6.4のpug関連のパッケージをインストールする部分

pug-plain-loaderの追加が必要です。

誤 npm install --save-dev pug
正 npm install --save-dev pug pug-plain-loader

P.227,p.228 6章「コラム カスタムブロックの定義」内のVue Loader周りの最新版での動作

誤 $ npm install --save-dev deepmerge marked
正 $ npm install --save-dev marked
誤


const merge = require('deepmerge')
const loader = require.resolve('./loader.js') // カレントディレクトリに作成したカ
スタムローダーを読み込む
module.exports = {
  chainWebpack: config => {
    // Vue Loaderの設定をカスタマイズする
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options =>
        merge(options, {
          loaders: {
            // カスタムブロックをインポートしたカスタムローダーで処理する
            docs: loader
          }
      })
    )
    .end()
  }
}


正



const loader = require.resolve('./loader.js') // カレントディレクトリに作成したカスタムローダーを読み込む

module.exports = {
  chainWebpack: config => {
  // Vue Loaderの設定をカスタマイズする
    config.module
      .rule('docs')
      .resourceQuery(/blockType=docs/)
      .use('docs')
      .loader(loader)
  }
}



P.287 7.7.2の最後の説明

誤 ここで上げた2つの手法は
正 ここで挙げた2つの手法は

P.236 7.1の最後のリスト内のimport

誤

import TaskList from './TaskList'

正

import TaskList from './TaskList.vue'

P.251 7章の脚注*15

「この例では、incrementAsyncを使わずに書くと以下のようになります」の一文は必要ありません。

誤 この例では、incrementAsyncを使わずに書くと以下のようになります。この例では、incrementAsync...
正 この例では、incrementAsync...

P.278 7.6.1のストア登録に関する説明

誤 アクションがどのようにストアに登録にされるかを
正 アクションがどのようにストアに登録されるかを

P.286 7.7.2の説明文中の氏名の表記

誤 Danは初めから正しく分類...
正 Dan氏は初めから正しく分類...

補足情報

P.167 # 5.2.3のslot-scopeを使った例がVue 2.6.0以降で動かない例

(2019年9月10日更新)

v2.6からslotはroot elementが必須になり,v-ifを用いた本書のサンプルは動作しなくなっていました。v2.6以降で動作を試したい場合は下記のようにv-showに修正して試してください。


<!DOCTYPE html>
<title>Vue app</title>
<!-- 最新のvue読み込み -->

<div id="app">
  <todo-list :todos="todos">
    <li v-show="todo.isCompleted" slot-scope="{ todo }" :key="todo.id">
        {{ todo.text }} 
    </li>
  </todo-list>
</div>


var TodoList = {
  props: {
    todos: {
      type: Array,
      required: true
    }
  },
  template: `
    <ul>
      <template v-for="todo in todos">
        <!-- v-bindディレクティブでtodoを親コンポーネントに渡す -->
        <slot :todo="todo">
          <li :key="todo.id">
            {{ todo.text }}
          </li>
        </slot>
      </template>
    </ul>
  `
}

new Vue({
  el: '#app',
  data: function() {
    return {
      todos: [
        { id: 1, text: 'C++',        isCompleted: true   },
        { id: 2, text: 'JavaScript', isCompleted: false  },
        { id: 3, text: 'Java',       isCompleted: true   },
        { id: 4, text: 'Perl',       isCompleted: false  }
      ]
    }
  },
  components: {
    TodoList: TodoList,
  }
})

P.370〜P.372 # 10.3.1のloginアクションハンドラに関するテスト

(2019年5月10日更新)

一部のコードがVue.js本体の変更に伴い動作しなくなっていました。Vue 2.6 以降では,Vue.nextTick のタスクが下記のissue対応によって処理されるタイミングが変わってしまったため(MutationObserverによるmicroTask),イベントループでうまく処理されなくなってしまいました。

以下のように Vue.nextTick を使わずに, Promise.then ,Promise.catch で done をハンドリングすることで,アサーションできるように修正してください。diff形式で掲載しています。


- import Vue from 'vue'
  import * as types from '@/store/mutation-types'
  
  // loginアクション内の依存関係をモック化する
  const mockLoginAction = login => {
    // inject-loaderを使ってアクション内の依存関係をモック化するための注入関数を取得する
    const actionsInjector = require('inject-loader!@/store/actions')
  
    // 注入関数でAuth APIモジュールをモック化する
    const actionsMocks = actionsInjector({
      '../api': {
        Auth: { login }
      }
    })
  
    return actionsMocks.default.login
  }
  
  describe('loginアクション', () => {
    const address = 'foo@domain.com'
    const password = '12345678'
    let commit
    let future
  
    describe('Auth.loginが成功', () => {
      const token = '1234567890abcdef'
      const userId = 1
  
      beforeEach(done => {
        const login = authInfo => Promise.resolve({ token, userId })
        const action = mockLoginAction(login)
        commit = sinon.spy()
  
        // loginアクションの実行
        future = action({ commit }, { address, password })
-       Vue.nextTick(done)
+       future.then(() => done())
      })
  
      it('成功となること', () => {
        // commitが呼ばれているかチェック
        expect(commit.called).to.equal(true)
        expect(commit.args[0][0]).to.equal(types.AUTH_LOGIN)
        expect(commit.args[0][1].token).to.equal(token)
        expect(commit.args[0][1].userId).to.equal(userId)
      })
    })
  
    describe('Auth.loginが失敗', () => {
      beforeEach(done => {
        const login = authInfo => Promise.reject(new Error('login failed'))
        const action = mockLoginAction(login)
        commit = sinon.spy()
  
        // loginアクションの実行
        future = action({ commit })
-       Vue.nextTick(done)
+       future.catch(() => done())
      })
  
      it('失敗となること', done => {
        // commitが呼ばれていないかチェック
        expect(commit.called).to.equal(false)
  
        // エラーが投げられているかチェック
        future.catch(err => {
          expect(err.message).to.equal('login failed')
          done()
        })
      })
    })
  })

商品一覧