Vue.jsのインライン記法
以前、このページではバージョン2のVue.jsをビルドせずに(インラインで)使う方法を紹介していましたが、Vue.jsのバージョン3になったのでそちらの記法でリライトします。
近年では、Vue.jsをインラインで記述することはあまり推奨されていないようです。ビルドしてアプリのサイズを小さくする事が望ましいということは分かりますが、HTMLファイルの記述を修正するだけでコードのメンテナンスができるインラインはやはり魅力的です。また、Node.jsなしでVue.jsの機能に触れることができるので、Vue.jsの初期の学習にも向いていいると思います。
Vue.jsの基本
基本的な部分はバージョン3でも変わりません。Vue.jsに初めて触れる人向けに、その説明を簡単にするとHTMLタグとJavaScriptの融合させたものです。(少し乱暴すぎるまとめ方かもしれませんが)
インライン記法に限りませんが、構成はテンプレート(HTML)部とコンポーネント(JavaScript)部に分かれ、テンプレート部に対して、Vue.jsのコンポーネントのインスタンスを適用させて利用します。
テンプレート部の記述
テンプレート部では次のような記述をします。
- Vueインスタンスの適用範囲
Vueのインスタンスを適用する範囲をHTML(テンプレート)に記述します。あとからidやclassを利用して対象を指定するので、わかりやすい名前を付けておきます。
sample.html
<div id="app"> <!-- この中で下に示すようなVue.jsの記法が使えます --> </div>
- {{ 変数 }}
Vueインスタンスの、適用範囲の内側では{{}}で囲まれた中で、Vueインスタンスの変数をそのまま利用できます。
ちなみに、LaravelにVue.jsを設定した場合は、Laravelでも{{}}を同じように利用するため、Vue.jsの{{}}は先頭に@を付けてエスケープします。
- v-bind:
HTMLタグの属性値として、Vue.jsの変数の値を使いたい場合は属性の前にv-bind:を付与すると、クォート内で変数が使えます。
また、v-bind:は:の一字に省略できます。
変数と文字列を連結したい場合もあると思います。その際はクォート内をバッククォートで囲んだ後変数に${}を付与します。
sample.html
<input type="text" v-bind:value="変数1" /> <input type="text" :value="変数2" /> <input type="text" :value="`${変数3} 様`" />
- v-html:
v-bindはHTMLタグをエスケープします。もしその挙動を止めたい場合は、v-htmlを使います。これを使う場合はセキュリティホールになりやすいので注意が必要です。
- v-model:
v-bind:はVue.jsのインスタンスから、HTMLテンプレートへ値を一方通行的に渡すものでした。input要素のvalueに設定する場合は、input要素値の変更を、Vue.jsインスタンスの変数に反映させたいことが多いと思います。その際に用いられるのが、v-model:です。これはinput、textarea、selectタグで使用できます。
- v-on:xxx(xxxにはclickやinputなどが入ります)
xxxの部分に指定されたイベントが起きた際に、実行するVue.jsインスタンスの関数を指定します。
v-on:は@の一字に省略できます。
sample.html
<button v-on:click="関数1">実行</button> <button @click="関数2">中止</button>
- v-if
v-ifの後に指定した条件式が真を返す時にHTMLタグを出力します。ここで記述されている「flag」はVue.jsのインスタンス中にある変数です。
連続したhtml要素で分岐ブロックを作っています。
sample.html
<p v-if="flag === '1'"> <!-- 1の時 --> </p>
<p v-else-if="flag ==='2'"> <!-- 2の時 --> </p> <p v-else> <!-- 1でも2でもない時 --> </p> - v-for
v-forを使って繰り返しHTMLタグを出力できます。
この時nは1から始まってループしながらカウントアップしていき、指定した値になった回を実行して終了します。
sample.html
<p v-for="n in 10">{{n}}回目</p> <!-- <p>1回目</p> <p>2回目</p> .... <p>10回目</p> -->
foreachのようはことも可能です。ここではmessagesがオブジェクトの配列になっていると仮定しています。
この時indexも取得できます。
sample.html
<ul> <li v-for="m in messages">{{m.message}}</li> </ul> <ul> <li v-for="(m,index) in messages">{{index}}-{{m.message}}</li> <ul>
配列からlengthを取得して数値をループさせ、オブジェクトから値を取得するとう方法もあります。
このときも値は1から配列の長さの回までループとなります。
sample.html
<table> <tr v-for="n in messages.length"><td>{{n-1}}-{{messages[n-1].message}}</td></tr> </table>
v-forではkey属性を利用して一意(他と重複しない)となる値を設定することを求められています。キーを設定してあると内部で行われる要素の再利用や削除において役に立つという事です。バージョン2では先のv-ifに関してもそれを推奨されていましたが、バージョン3ではv-if,v-else-if,v-elseにおいては自動的にキーを発行するようになりました。
sample.html
<ol> <li v-for="m in messages" :key="m.id">{{m.value}}</li> </ol>
コンポーネント部の記述と稼働サンプル
コンポーネント部はJavaScriptで記述しますので、scriptタグ内に記述します。
Vue.js用のデータ(変数群)、や関数、イベントなどを全てオブジェクトの中に定義し、それをコンストラクタに渡してインスタンスを生成します。
データはパラメータオブジェクト中のdataという名前の関数の戻り値としてオブジェクトの形で定義します。
関数は「methods」をキーにしたオブジェクトの中に定義します。
ライフサイクルにおけるイベントは、それに応じた名前の関数の中に定義します。
Vue.jsのインスタンスを生成と同時に、mountメソッドにセレクタを渡して対象となるテンプレートを指定します。
説明だけだとわかりづらいと思いますので、テンプレートと合わせてサンプルアプリを記述しました。
sample-app.html
<!-- テンプレート部 -->
<div id="countup-app">
<p>現在のカウント数は {{intCount}} です。</p>
<p><button @click="countUp()">カウントアップ</button></p>
</div>
<!-- CDNからVue.js Ver3を取得 -->
<script src="https://unpkg.com/vue@3.2.36/dist/vue.global.js"></script>
<!-- コンポーネント部 -->
<script>
//パラメータオブジェクト
const params = {
data() {
return { intCount: 0 }
},
mounted() {
this.intCount=1;
},
methods:{
countUp(){
this.intCount++;
}
}
}
//設定したオブジェクトを使って、インスタンスを生成
Vue.createApp(params).mount('#countup-app')
</script>
ちなみにオブジェクトにある「data(){...}」として関数を記述する方法は、「data: function(){...}」と記述する省略法だそうです。
【 サンプルアプリ 】
現在のカウント数は {{intCount}} です。
ちなみに、インラインで実行すると次のように、ビルド環境を利用するようにというメッセージが出力されます。以前は警告メッセージ(オレンジ)だったような覚えもあるのですが、単なるメッセージ(黒色)になっていました。
Make sure to use the production build (*.prod.js) when deploying for production.
外部コンポーネントを利用する
CDNなどで配布されているVue.js用のコンポーネントを利用する場合、バージョン3では次のようにします。
まずグローバル領域にセットする場合はcreateAppメソッドを実行した後componentメソッドを使います。
ブラウザ経由でCDNから取得できる例示に使えるようなVue3用のコンポーネントが見つからなかったので、ここではコンポーネントを直に記述しています。
sample-updown.html
...
<div id="countupdown-app">
<sample title="コンポーネント"></sample>
</div>
...
<script>
...
//コンポーネント本体
const component = {
name: 'decrement',
props: {
title: String
},
data(){
return { intCountD: 100 };
},
methods:{
countDown(){
this.intCountD--;
}
},
template:`<div>
<h3>{{ title }}</h3>
<p>
現在の値は {{intCountD}} です。
</p>
<button @click="countDown()">カウントダウン</button>
</div>`
};
Vue.createApp(params).component('sample',component).mount('#countupdown-app');
...
パラメーターとしてセットする場合はバージョン2の時とほとんどかわりません。パラメーターのcomponentsキーに渡すオブジェクトの中で設定します。
sample-updown.html
...
<div id="countupdown-app">
<sample title="コンポーネント"></sample>
</div>
...
<script>
...
//コンポーネント本体
const component = {
name: 'decrement',
props: {
title: String
},
data(){
return { intCountD: 100 };
},
methods:{
countDown(){
this.intCountD--;
}
},
template:`<div>
<h3>{{ title }}</h3>
<p>
現在の値は {{intCountD}} です。
</p>
<button @click="countDown()">カウントダウン</button>
</div>`
};
const params = {
...
components: {
'sample': components
},
...
}
Vue.createApp(params).mount('#countupdown-app');
...