Nuxt.jsを使ってみたい!
いきなりタイトルとは違うところを書きましたが、Nuxt.jsを使うためにはVue.jsの知識が必要。
Vue.jsから一から学んでいく時にメモ+まとめ的につらつらと書いていきます。
誤字や誤認識もあるかと思いますが、その際はご指摘をいただけると非常に助かります
参照したもの
準備
簡単に打鍵しながら学びたいので、jsfiddleを使ってます。
HTMLとJS簡単に試せます。
詳しい使い方として、こちらのサイトを参考にさせていただきました。
簡単にコードを実装してシェアできる!超便利なjsFiddleの使い方
ちなみに開発時はVSCodeを使ってます。便利なプラグインも多くて助かります。
サーバーサイドも一緒に開発する時にはIntellJです(Kotlin&SpringFramework)。
1.概要
まずは本家のサイト を参考に。
ざっとみて、以下の点か重要かなと。
- テンプレート構文を使って、MVVMしてる
- ディレクティブを使って、DOMにリアクティブ可能。
- タグの属性に処理を設定できる
- タグ自体の分岐やループ等の処理もできる
- イベントハンドラの設定もできる
- コンポーネントシステムを使って、再利用可能な小さい部品を作って使いまわせそう
- アトミックデザインに適した実装が可能かな?
- でかいシステムでも、設計をちゃんとすれば複数人数で開発できそう
2.Vue定義
Vueインスタンス
Vueにはフィールドとメソッド等を定義可能。
Javaエンジニアなので、属性と振る舞いという観点で理解しようとする。
- 属性(一部)
- data
- Vueインスタンスプロパティの1つ。
- ここで定義したものがインスタンス化された時にgetter/setterが用意・監視され、リアクティブを実現している。
- el
- Vueインスタンスを作成後、DOMにマウントするときに指定する
- もしVueのフィールドに指定しない場合、どこのDOMにもマウントされない。その場合は、
vm.$mount(#app-0)
をコールしてマウントする。
- data
- 振る舞い
- methods
- Vue.jsではメソッドと呼ばれる。
- Vueコンポーネントが少しでも変わったら、実行される。
- 使いまくるとことある毎に画面が再描画されることもある。よって、あんまり使わない方が良い。
- 引数が無くても()はつけるのが無難。例:
changeMethod()
。-
changeMethod
でも書けるけど、どっちかに統一するのが無難。
-
- computed
- Vue.jsでは算出プロパティと呼ばれる。
- return が必ず必要。特殊なGetterのようなイメージ。
- レスポンスの内容を毎度キャッシュしており、レスポンスの内容が変わる場合のみ、実行される。
- 再描画のタイミングが少ない。
- methodsよりもこちらを使った方が良い。
- 使用頻度が一番高くあるべき
- ()はつけちゃだめ。プロパティと呼ばれるだけある。例:
changeComputed
- watch
- Vue.jsではウオッチャと呼ばれる。
- インスタンスフィールドを監視する。
- 関数名に必ずインスタンスフィールド名を設定する。
- 非同期処理の実行や、処理のタイミングを制御できる。
- return は不要というより設定できない。
- computedでは対応できないような複雑な実装が必要な場合に使用する。
- methods
Vueインスタンスの作成方法は簡単。ViewModelにあやかってvm
という変数名をつけることが多いみたい。
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-0">
<button v-on:click="changeMethod()">メソッドを実行します</button>
<p>{{ mehodsStr }}</p>
<hr>
<p>{{ changeComputed }}</p>
<hr>
<button @click="watchStr = '監視スタート'">ウオッチャを実行します</button>
<p>{{ watchStr }}</p>
</div>
var vm = new Vue({
// DOMへのマウント定義
el: '#app-0',
data: {
mehodsStr: 'メソッド初期値',
watchStr: 'ウオッチャ初期値'
},
methods:{
// メソッドが呼ばれるときだけでなく、
// 再描画されるタイミングに毎回呼ばれる
changeMethod: function() {
this.mehodsStr = 'メソッドが実行されました'
}
},
computed:{
// インスタンス作成時に初回実行され、
// レスポンスが変わるタイミングでのみ実行される。
// 今回のパターンは、文字列のハードコードのため、
// 2度と呼ばれることは無い。
changeComputed: function() {
return "算出プロパティ変更後"
}
},
watch: {
// 非同期処理を実装できる
watchStr: function () {
var vm = this;
setTimeout(function(){
vm.watchStr = "3秒後に実施されました"
}, 3000)
}
}
})
Vueインスタンスのライフサイクル
以下が、Vueインスタンスのライフサイクル。
- beforeCreate
- インスタンスが作られる前。
- dataにもアクセスできない=作られていない
- created
- インスタンスが作られたあと
- dataのgetter/setterも作られ、リアクティブ状態になる
- beforeMount
- $elを作ってDOMに追加する前
- インスタンスに
el
が含まれていない場合:$mount()がコールされる -
template
をrender関数でコンパイル=仮想Nodeを作る - 仮想DOMにする前
- mounted
- 仮想DOMを実際のDOMにマウントされた後
- beforeUpdate
- 仮想DOMが変わった時に、DOMを再描画する前
- updated
- 仮想DOMが変わった時に、DOMを再描画した後
- beforeDestroy
- 破棄する前
- destroyted
- 破棄した後
Vueインスタンスのライフサイクルをトリガーにフックしたくなる時は以下を参考に。
new Vue({
data: {
a: 1
},
// createdのフック
created: function () {
console.log('a is: ' + this.a)
}
})
data
- インスタンスプロパティの一つ。 全てのインスタンスプロパティはこちら
- Vueインスタンスを監視しているデータオブジェクト。
- Vueを定義する時のdataは、外部のオブジェクトを指定することも出来る。
var hoge = { a: 1 }
// インスタンスを直接生成
var vm = new Vue({
data: hoge
})
vm.a // => 1
vm.$data.a // => 1
vm.$data === hoge // => true
注意点がいくつかある。
- $dataに設定できるオブジェクトはプレーンなもの。
template
DOMを置換するのに使用可能。
ハードコードっぽくなりやすいので使いにくいかな。
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app-2-2">
<!-- 置き換えられるので、spanは表示されない -->
<span v-bind:title="message">
Hover your mouse over me for a few seconds
to see my dynamically bound title!
</span>
</div>
var app2 = new Vue({
el: '#app-2-2',
data: {
message: 'You loaded this page on ' + new Date().toLocaleString()
},
template: '<h1>{{message}}</h1>'
})
結果
render
- createElementで仮想Node(VNodeという)を作って、render関数で仮想DOMを構築してDOM要素を作る(まだしっくりきていない・・・)
- createElementは、第一引数をタグ名、第二引数をDOM要素とする
var app2 = new Vue({
el: '#app-2-2',
data: {
message: 'You loaded this page on ' + new Date().toLocaleString()
},
// template→renderに
render: function(createElement) {
return createElement('h1', this.message)
}
})
3.テンプレート構文
もっとも基本的なデータバインディングは、二重中括弧を利用したもの。
この「二重中括弧」、”Mustache(むすたっしゅ)” 構文という。初めて知ったけどそれは隠そうと思う。
<!--Vueインスタンスのmsgフィールドの情報をバインディングする。 -->
<span>Message: {{ msg }}</span>
JSでmsgフィールドの内容が変更されたら、上記の内容も変更されます(双方向バインディング)。
ただし、一度表示したらmsgフィールドの内容がかわろうとも、変更されないような書き方もあります。
v-once
ディレクティブを使います。
<span v-once>This will never change: {{ msg }}</span>
このように、痒いところに届きそうなものから、すげー使うやつまでディレクティブの種類が多すぎそうなので主要なものと言われるのをまとめてみます。
4.ディレクティブ
5.修飾子
6.仮想DOM
仮想Node(VNode)をcreateElement()で作成して、render関数で返すと仮想DOMが作られDOM要素として展開される。
通常、DOMノードに対してアクセスすると処理が遅い。それを解消するための仕組み(と思っている・・・)。
詳細にいうと、仮想DOMで差分を検知したら、実際のDOMノードの差分を更新するという仕組み。
以下の例でいうと、仮想DOMがthis.messageの変更を検知して(このサンプルでは変更されることはないけど・・・)、
実際のDOMノードを変更する。
var app2 = new Vue({
el: '#app-2-2',
data: {
message: 'You loaded this page on ' + new Date().toLocaleString()
},
// template→renderに
render: function(createElement) {
return createElement('h1', this.message)
}
})
7.Vueコンポーネント
8.Vue CLIとVue Component
9.フィルター
10.ミックスイン
11.カスタムディレクティブ
99.その他
クラスとスタイルのバインディング
本家のサイトには、以下の技が載っているのでご参考までに。
-
HTMLクラスのバインディング
-
オブジェクト構文
- 例:
<div v-bind:class="{ active: isActive }"></div>
- 例:
-
配列構文
- 例:
<div v-bind:class="[activeClass, errorClass]"></div>
- 例:
-
コンポーネントを使ったバインディング
- 例:
<my-component v-bind:class="{ active: isActive }"></my-component>
- 例:
-
オブジェクト構文
- インラインスタイルのバインディング
this.が使えない箇所
基本的には、インスタンスプロパティをそのまま使う様な箇所でしか使えないイメージ。
ユーティリティのようなフィルターや、各要素に対して適用させるようなカスタムディレクトリについては使えなそう。
- カスタムディレクティブでは使えない
- フィルターでは使えない
※以下、随時追加。