概要
Vue.jsを初めて触る人に向けたサンプルと解説です。
React.jsと比較する形で書いています。
Vue.jsとは
原作者であるEvan You氏が中心となって開発中の、Javascriptフレームワークです。
日本語の公式サイトがあるため、初心者にもかなり分かりやすいです。
環境構築
vue-cliというコマンドラインツールが主流です。
単一ファイルコンポーネント
VueはReactと同じく、パーツ単位でHTMLをまとめるコンポーネント指向ですが、.vue拡張子の単一ファイルコンポーネントによって、その「パーツを構成するために必要な HTML・CSS・JSをひとまとめに」して独立した1つのファイルで扱うことができます。
それぞれ<template>
、<script>
、<style>
が担当します。
<template>
<div class="say-hello">Hello!!<div>
</template>
<script>
export default {
name: 'Hello'
}
</script>
<style scoped>
.say-hello {
font-weight: bold;
}
</style>
コンポーネントオプション
name
コンポーネント名を表現します。
components
他のコンポーネントをimportして使いたい場合はここに記述しておく必要があります。
props
親コンポーネントから渡されたpropsを使いたい場合はここに記述しておく必要があります。
なお、propsの型をここで指定することができます。書き方は以下を参照してください。
data
Reactでいうstateです。以下のように定義することで、template内で{{ }}
で囲うことで出力できるようになります。
data: function () {
return {
msg: 'Hello World!'
}
}
<p>{{ msg }}</p>
methods
Reactでいうハンドラです。以下のように定義します。
methods: {
greet: function (event) {
alert(event.target.tagName)
}
}
次にgreetメソッドにclickイベントリスナをバインドします。
これによってボタンが押されたときにBUTTONというアラートが出ます。
<button v-on:click="greet">Greet</button>
インラインメソッドハンドラ
メソッド名を直接指定する代わりに、インラインJavaScript式でメソッドを指定することもできます。
methods: {
say: function (msg) {
alert(msg)
}
}
<button v-on:click="say('hi')">Say hi</button>
computed
算出プロパティといいます。返り値が必須です。通常のプロパティと同様に、template内でデータバインドすることができます。
またある算出プロパティに依存されているプロパティが変更されると、この算出プロパティに依存する全てのバインディングを更新します。
算出プロパティの代わりに、同じような関数をメソッドとして定義することも可能です。最終的には、2つのアプローチは完全に同じ結果になります。
算出プロパティの場合
computed: {
reversedMessage: function () {
return this.msg.split('').reverse().join('')
}
}
<p>{{ reversedMessage }}</p>
メソッドの場合
methods: {
reverseMessage: function () {
return this.msg.split('').reverse().join('')
}
}
<p>{{ reversedMessage() }}</p>
違いは、「算出プロパティは依存関係にもとづきキャッシュされる」ということです。
算出プロパティは、それが依存するものが更新されたときにだけ再評価されるのに対し、メソッド呼び出しは、再描画が起きると常に関数を実行します。
キャッシングする必要の有無によって使い分けてください。
ディレクティブ
Reactではjsxファイル内で普通にjavascriptで条件分岐やループ処理を書きますが、Vueにはディレクティブという特殊な書き方があり、よりシンプルに書けます。
v-bind
プロパティを渡します。
<input type="text" v-bind:value="msg" />
なお、以下のように省略して記述できます。
<input type="text" :value="msg" />
v-on
イベントを受け取ります。
<input type="text" v-on:input="msg" />
なお、以下のように省略して記述できます。
<input type="text" @input="msg = $event.target.value" />
v-model
Reactは「データ」→「画面(HTML)」という方向でしかデータが流れない、一方向データバインディングですが、
Vueでは双方向データバインディングを書くことができます。
データと表示をバインドします。
<p>{{msg}}</p>
<input type="text" v-model="msg" />
これは以下と同じ意味です。
<p>{{msg}}</p>
<input type="text" :value="msg" @input="msg = $event.target.value" />
一方向にしたい場合は:か@の片方だけにすればいいです。
v-if
条件分岐です。
下記はtodoのeditingプロパティがtrueなら入力フォームを、falseならテキストを表示する例です。
<input v-if="todo.editing">
<span v-else>{{ todo.text }}</span>
v-for
ループ処理です。
keyにはユニークな値をセットする必要があります。ただし、:key
というように独特の記述の仕方があるので注意してください。
<div v-for="item in greetings" :key="item.id">{{ item.text }}</div>
data: function () {
return {
greetings: [
{
id: 1,
text: 'おはよう!'
},
{
id: 2,
text: 'こんにちは!'
},
]
}
}
親コンポーネントから子コンポーネントにpropを渡す
静的な値(文字列など)は以下の書き方で親コンポーネントから子コンポーネントにpropとして渡せます。
<blog-post title="My journey with Vue"></blog-post>
動的な値を渡す場合は変数の値をバインディングする必要があります。
なお、静的な値を以下の書き方で渡すこともできます。
<blog-post :title="post.title"></blog-post>
ライフサイクル
created
インスタンスが作成された後に呼ばれます。
mounted
インスタンスがマウントされた後に呼ばれます。
ReactでいうcomponentDidMount()
のようなものです。