【輪読会資料】基礎から学ぶVue.js CHAPTER7 より大規模なアプリ開発 読書メモ
以下の記事は2019/3/28 コワーキングスペース秋葉原Weeybleで行われる輪読会
[秋葉原] 基礎から学ぶVue.js輪読会 ch7 より大規模なアプリ開発(初心者歓迎!)のための読書メモとなります。
以下の書籍の CHAPTER7 より大規模なアプリ開発 のメモです。

- 作者: mio
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2018/05/29
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
CHAPTER 7 より大規模なアプリケーション開発
SECTION 33 アプリケーションを拡張しよう
Vue.js本体は画面の描画に関わる機能しか備えていないが、以下の様なエコシステムを導入すると機能を拡張できる。
Vuex
複数のコンポーネントでデータを共有したり、アプリケーション全体の状態を一元管理する状態管理用のライブラリ
Vue Router
コンポーネントで構造化された複数の画面をURLと紐づけるSPA(Single Page Application)構築の為のルーティング用のライブラリ
Vuex と Vue Routerは機能として独立しており、状況に応じて片方だけでも構築が可能。 それぞれの特徴はCHAP8,CHAP9で解説している。
ここでは単一ファイルコンポーネントを使ったコンポーネント構築とVueCLIを使ったビルド環境の導入を前提としての説明をする。
SECTION 34 Vue CLIとは
Vue CLIとはVue.jsを使ったコマンドラインインターフェース、Vue.jsの開発環境構築が簡単にできる
ソースコードを分けて管理
分割して作ったファイルをコンパイル時等に結合して一つのファイル化させる方法
モジュール化でさらに快適に!
モジュール化で作られたファイルは多くの機能から必要なものだけピックアップして組み込める。
Vue.jsのモジュール化は「単一ファイルコンポーネント」を採用している。
単純に結合しても動くわけではなく、補完する機能として代表的なものに「webpack」といったバンドルツールがある。
webpack以外にも多くのツールの複雑な設定を自動管理してくれるのが「Vue CLI」となる
webpackとは
モジュール化した複数のファイルをまとめるバンドルツール、他にも[Rollup]や[Parcel]といった別種が存在する。詳細は公式サイトを参照の事 webpack 公式サイト
モジュール化の際は、必要なリソースだけをバンドルするようになっているので、自動的に余計なものが付かないで最小単位で出力されるようになっている。
SECTION 35 単一ファイルコンポーネントとは
「単一ファイルコンポーネント」はコンポーネントの定義方法の一つでSFC(Single File Components)
とも言われる
一つのファイルで管理しきれないHTML,JavaScript,CSSを[.vue]という拡張子のファイルにまとめて管理する。
単一ファイルコンポーネントの例
Example.vue
<template> <div class="example"> <span class="title">{{ text }}</span> </div> </template> <script> export default { name: 'Example', data() { return { text: 'example' } } } </script> <!-- scoped CSS --> <style scoped> .title { color: #ffbb00; } </style>
こいつをビルド環境でプレーンなJavaScriptにプリコンパイルする
スコープ付きCSS(Scoped CSS)
<style>
タグでscoped
オプションを付けるとスコープ付きCSSを利用できる。(<style scoped>
)このテンプレート内でしかスタイルが適用されないようにできる。
出力される際には以下の様なユニーク属性で管理される
<div class="example" data-v-xxxxx> <span class="title" data-v-xxxxx> hoge </span> </div>
span.title[data-v-xxxxx] { color: #ff0000; }
これでクラス名の衝突を気にしなくて良くなる。なお、全くクラスの指定がないとパフォーマンスが落ちるので classでスタイル定義をするのが推奨されている。
子コンポーネントの扱い
テンプレート内に子コンポーネントが存在する場合、子のルート要素とスロットの要素は親と子の両方のスコープを持つ
<div class="example"> <child-comp/> </div>
親と子両方に<style scoped>
をを指定した際は以下の様に展開される
<div class="example" data-v-aaaaa> <div data-v-aaaaa data-v-bbbbb><!-- このルート要素 --> <span data-v-bbbbb>child-comp</span> </div> </div>
この様にルート要素のスタイルはどちらのファイルにも書くことができるので、柔軟にレイアウト変更が可能となる。
スコープをまたぐ設定
お互いにスコープの付いたコンポーネントから子のセレクタ .b
を指定したい例
cssの場合
<style scoped> .a >>> .b {color: #ff0000; } </style>
scssの場合
<style lang="scss" scoped> .a /deep/ .b {color: #ff0000; } </style>
外部ファイルの読み込み
<template src="./template.html"></template> <style src="./script.js"></style> <style src="./style1.css"></style> <style src="./style2.css" lang="scss" scoped></style>
他のマークアップ言語やスタイルシート言語の仕様
cssやscssの他に、[Pug],[Sass]を使用等をすることができる。Vue CLIで作成したプロジェクトなら、パッケージを以下の様にインストールしてから…
npm install pug pug-loader --save-dev
以下の様に書くだけで使用可能
<template lang="pug> div#example span {{ text }} </template>
SECTION 36 ES2015モジュールの書き方
ES2015モジュールは .js でファイルを作成するが、モジュールファイルは独自のスコープを持ち、他のファイルとは切り離される、変数の衝突や他の機能への干渉を気にしなくて良くなる反面、モジュール内で定義したデータや関数は他のファイルから直接アクセスできなくなる。
モジュールを定義する
Example.js
// stateオブジェクトはこのモジュール内でしか使用できない var state = { count :1 }
モジュール内のデータや関数を別のファイルに渡すにはエクスポート&インポートが必要
次の例はstate
オブジェクトをエクスポートして、外部でインポートできる様にした例
Example.js
var state = { count :1 } // デフォルトのインポート文で呼ばれた時に返すデータ export default state
モジュールを使用する
前述のExample.js
のstate
オブジェクトをExample
という変数名でインポートした例
main.js
import Example from './Example.js' console.log(Example.count) // => 1と出力
このような書き方は Vuex, Vue Router ファイルを書く際に必要なので覚えておくこと!
SECTION 37 Node.jsの導入
node.js
はJavaScriptの実行環境、サーバーサイドでJSを動かす際に必須
npm
はJSのパッケージ管理ツール、node.jsに一体化して付いてくる。 PHPでいう所のcomposer的な奴
以下からインストール
node.js 日本語公式サイト
windows10の場合はそのまま画面の指示に従いインストール
コマンドプロンプトで以下のコマンドでバージョンを出してインストールされたか確認する。
今回は推奨版10.15.3 LTS をインストールした
node -v v10.15.3 npm -v 6.4.1
Babelとは
ECMAScript準拠およびJSXのトランスパイラ、Vue CLIはデフォルトでBabelをインストールしてトランスパイルを行う。
トランスパイル(transpile)
一言で言えば、ある言語で書かれたコードを元に別の言語のコードを生成すること。
BabelはES2015のコードを古いES5のコードに変換してくれる
ES2015のコード | トランスパイル | ES5のコード |
---|---|---|
const count = 1 | => | var count = 1 |
Babelの目的やメリットは最新の記法を使って書ける様にすることにある
SECTION 38 Vue CLIの導入
Vue CLIをインストール
npm install -g vue-cli
バージョンを確認
vue --version 2.9.6
プロジェクト作成コマンドのひな形
vue init [テンプレート名] [プロジェクト名] cd [プロジェクト名] npm install
テンプレートは[webpack], [webpack-simple]が良く使われる,他にも[PWA],[Electron]等の様々なアプリケーション用のテンプレートが公開されている。
ここでは[webpack]を使って説明をして行く
新しいプロジェクトの作成
アプリを入れたい適当なフォルダに移動(cd)してから次のコマンドを実行
(Git bashで操作)
作ったフォルダ自体が localhost:8080 の実行環境になってそのまま開発環境のsever化してくれるので、本当にフォルダの場所とか適当で良い様です。
# htdocsに移動 $ cd /c/xampp/htdocs # プロジェクトの作成 vue init webpack vue-my-app $ vue init webpack vue-my-app # 質問が出るので色々選択しながら進む、今回は以下の設定で進んだ。 ? Project name (vue-my-app) ? Project name vue-my-app ? Project description (A Vue.js project) ? Project description A Vue.js project ? Author (Taro Yamada <yamada@gmail.com>) ? Author Taro Yamada <yamada@gmail.com> ? Vue build runtime ? Install vue-router? (Y/n) n ? Install vue-router? No ? Use ESLint to lint your code? (Y/n) n ? Use ESLint to lint your code? No ? Set up unit tests (Y/n) n ? Set up unit tests No ? Setup e2e tests with Nightwatch? (Y/n) ? Setup e2e tests with Nightwatch? Yes ? Should we run `npm install` for you after the project has been created? (recom ? Should we run `npm install` for you after the project has been created? (recom mended) npm
すると htdocs
フォルダ内に vue-my-app
フォルダが作られ、中に色々ファイルが作られる
$ ls -a vue-my-app/ ./ .babelrc .gitignore build/ index.html package.json README.md static/ ../ .editorconfig .postcssrc.js config/ node_modules/ package-lock.json src/ test/
フォルダとファイルの構成
[webpack]を使用した際、いろんなファイルやフォルダが作られるが、基本的に[src]フォルダ以下の物しか使わない
単一ファイルコンポーネントの[.vue]ファイルは慣例的に src/components
にまとめる
src/main.js でコンストラクタの呼び出しが行われている
/* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(App) })
開発サーバーを起動する
vue-my-app
フォルダ内に cd してから以下のコマンドを入れてサーバーを起動する
npm run dev
ブラウザでhttp://localhost:8080/
にアクセスしてVue.jsのロゴとWelcome to Your Vue.js App のメッセージが出力されればOK!
サーバーを起動させたコンソールは開きっぱなしにしておくこと
ホットリロード
ホットリロードはブラウザリロード不要でファイル変更の際に更新してくれる機能
vue-my-app/src/components/HelloWorld.vue
ファイル内のmsg: 'Welcome to Your Vue.js App'
を編集して上書きすると即座ぶブラウザが更新されるのが確認できる。超便利!
プロジェクトをビルドする
実際に運用モードとしてビルドするには以下のコマンドを入れる
npm run build
数分かかる。ビルドが終わると[dist]フォルダが作成される。
この[dist]フォルダだけを本番サーバーにアップロードすれば、ローカルからのビルドとデプロイが完了する。
ちなみに以下のサポートページで、静的サイト向けの高機能なホスティングサービスNetlify
の自動デプロイの方法についての記述がある。
Vue.js+Netlifyで自動デプロイ
開発時のAPIのパス統一やクロスドメイン対策
本番環境と開発環境でAPIのパスが異なる場合や、別ドメインのAPIからデータを取得する際はプロキシ設定が必要となる。config/index.js
に以下の様に記述することで切り替えができる
before config/index.js
proxyTable: {},
after config/index.js
proxyTable: { '/api' : { taget: 'http://localhost:8081', changeOrigin: true, pathRewrite: { '^api'; '/vue-my-app/api' } } },
例えばAPIで /api/user
を叩くと 異なるドメインから user のAPIを取得できるように実装がされているとする。
プロキシを使うと以下へのアクセスは
http://localhost:8080/api/user
以下の様に変更できる
http://localhost:8081/vue-my-app/api/user
より詳細はwebpackのドキュメントを参照のこと
SECTION 39 Vue.jsプラグイン
CHAPTER1で紹介されたElement,Awesome Vue,VueCurated等のUIコンポーネントや、Vuex,Vue RouterはVue.jsプラグインとして作成されている。
ここではVue.jsプラグインの使い方と自作プラグインの作成方法の紹介となる。
Vue.jsプラグインの使い方
コンストラクタを使用する前にグローバルメソッドのVue.use
を使用してVue.jsに登録する
src/main.js の上の行に書く?
// VueとVuexのモジュールを読み込む import Vue from 'vue' import Vuex from 'vuex' // VueにVuexを登録 Vue.use(Vuex)
スタンドアロン版でプラグインを使用する場合
Vuexの様な公式提供の奴はVue.use
を使わずとも良い。
Vue.js本体を読み込んだ後にプラグインのファイルを読み込む
公開されているリソースはプラグインだけじゃない
コンポーネントやカスタムディレクティブとして登録するのものある
プラグインを自作してみる
入門向けではないが一応説明、大規模アプリの開発リソースの再利用の際にプラグイン作成できると便利だそうな。
具体的にどのファイルのどこに書けばいいのか分らずなのだが、それはここまで読んだ内容を理解してないせいか、後の章で書かれるかだと思います。
スクロール数値を共有するプラグイン
var windowPlugin = { install: function(Vue) { // プラグインデータ用にVueインスタンスを利用する var store = new Vue({ data: { scrollY: 0 } }) // ウィンドウのスクロールイベントをハンドル var timer = null window.addEventListener('scroll', function() { if (timer === null) { timer = setTimeout(function() { // 200ms間隔でscrollYプロパティに代入 store.scrollY = window.scrollY clearTimeout(timer) timer = null }, 200) } }) // インスタンスプロパティに登録 Vue.prototype.$window = store.$data } }
プラグインを登録
Vue.use(windowPlugin)
すべての Vue インスタンスで使用可能
Vue.component('my-component', { template: '<div>{{ scrollY }}</div>', computed: { scrollY: function() { return this.$window.scrollY } } })
SECTION 40 ES2015で書いてみよう
新しいJavaScriptの書き方、ES2015(ES6)は対応してないブラウザがあるが、既に説明した通り、Babelが古いJS形式にトランスパイルしてくれるので、Vue CLI
ではES2015形式で遠慮せずに書ける。ここではES2015の書き方の説明となる。
正直ちゃんと追って無かったので、この知識はありがたい。
変数宣言
ES5
var x = 0
ES2015
// 再代入可能 let x = 0 // 定数 再代入不可 const x = 0
ES2015はスコープで仕切られる
ES5
{ var x = 1 } console.lod(x) // 1
ES2015
{ let x = 1 } console.lod(x) // not defined
constで宣言した配列は空配列を再代入できない。か、 length
を0にすると配列を空にできる
const array = [1, 2] array.push(3) console.log(array) // -> (3) [1, 2, 3] array.length = 0 console.log(array) // -> []
関数とメソッドの書き方
functionの省略
ES5
new Vue({ methods: { handleClick: function() { ... } } })
function は書かなくても良い
ES2015
new Vue({ methods: { handleClick() { ... } } })
アロー関数
functionを省略して =>
で書ける関数thisの扱いが従来の関数と異なり、アロー関数式で宣言された関数は、宣言された時点で、thisを確定(=束縛)させてしまう。
その為メソッド内のthis
が必要な場面では使用できないが無名関数の定義で便利とのこと
【JavaScript】アロー関数式を学ぶついでにthisも復習する話
let normalFunc = function(x){ console.log(x); } normalFunc('今までの関数'); let arrowFunc = (y) => { console.log(y); } arrowFunc('アロー関数式');
STEP1
const newArray = array.map(el => { return el * 2 })
STEP2 returnを省略
const newArray = array.map(el => el * 2)
慣れの問題だが、ここまで省略されると認識し辛いなぁ
STEP3 複数の引数
const newArray = array.map((el, index) => el * 2)
STEP4 オブジェクトの return
const newArray = array.map(el => ({ value: el * 2 }))
簡単な奴から使って慣れると良いよ。と作者もおっしゃってます。
テンプレートリテラル
クォーテーションで囲んでバックスラッシュで改行
ES5
var name = 'hoge' var template = '\ <div class="template">\ <strong>' + this.name + '</strong>\ </div>' console.log(template)
バッククォートで囲むだけで改行含めて受け付けてくれる
ES2015
const name = 'hoge' const template = ` <div class="template"> <strong>${ name }</strong> </div>` console.log(template)
オブジェクトプロパティのショートハンド
ES2015では変数名とプロパティが同じなら省略して書ける
ES5
const newObject = {a: a, b: b}
ES2015
const newObject = {a, b}
分割代入
べんりー
ES2015
// 配列要素1,2をそれぞれ変数a,bに代入 const [a, b] = [1, 2] console.log(a) // -> 1 // nameプロパティだけ代入 const { name } = { id: 1, name: 'りんご' } console.log(name) // -> りんご
引数のオブジェクトを分割して受け取ることも可能
ES2015
function myFunction({ id, name }) { console.log(name) // -> りんご } myFunction({ id: 1, name: 'りんご' })
v-for
ディレクティブでも使える
<ul> <li v-for="{ id, name } in list" :key="id">...</li> </ul>
スプレッド演算子
配列、オブジェクトのリテラルを展開する ...hoge
ES2015
const array = [1, 2, 3] // バラバラの3つの引数として渡す myFunction(...array) // arrayを展開して4を加えた新しい一次配列を作成 const newArray = [...array, 4] // -> (4) [1, 2, 3, 4]
配列メソッド
findメソッド
条件に一致した最初の要素の値を1つ返す
(そういえばこういう処理、スゲー大変だった気がする)
ES2015
const array = [ { id: 1, name: 'りんご' }, { id: 2, name: 'ばなな' } ] const result = array.find(el => el.id === 2) console.log(result) // -> { id: 2, name: 'ばなな' }
見つからない場合は undefind が返る
findindex
条件に一致した最初の要素のインデックスを1つ返す
const array = [ { id: 1, name: 'りんご' }, { id: 2, name: 'ばなな' } ] const result = array.findIndex(el => el.id === 2) console.log(result) // -> 1 (indexは0始まりなので2番目は1)
Promise
非同期処理を抽象化したオブジェクト。(もうajaxとかじゃない!)
Promiseで非同期処理の完了を知ることができる。
引数としてresolve
(解決した)と、reject
(拒否した)のコールバック関数を受け取る。
( $.ajaxの .done .fail みたいな感じか )
成功を知る例
function myFunction() { return new Promise((resolve, reject) => { setTimeout(() => { // 成功したことを通知 resolve('success!') }, 1000) }) } // 1秒後にmyFunctionが終わった知らせを受けてthenの処理が行われる myFunction().then(value => { console.log(value) // -> success! })
拒否(失敗)した事を知る例、かつ成功、失敗の両方の処理を書いた例
function myFunction(num) { return new Promise((resolve, reject) => { if (num < 10) { resolve('success!') } else { reject('error!') } }) } myFunction(100).catch(value => { console.log(value) // -> error! })
成功、拒否、どちらでも処理する際はfinally
を使う
myFunction().then().catch().finally(() => { // 成功でも失敗でも行われる })
Gitリポジトリからcloneして動かす際
プロジェクトフォルダをそのままリモートリポジトリに上げる。 別の環境でnode.jsをインストールして任意のフォルダで以下の操作をするだけでOK
git clone **url** npm install npm run dev
これだけで動く
□まとめ
- Vue CLI はVue.jsプロジェクトのベースを構築してくれる
- Vue CLI で単一ファイルコンポーネントを手軽に使用できる
- ES2015以降のECMAScriptを使ったコーディングが可能、基本を把握しておく