フロントエンドエンジニア必読vue.jsの基礎
本文書では、Vue.jsの勉強を始めた人またはVue.jsの基本機能をしっかり理解したい人を対象にVue.jsの基礎的な機能について説明を行っています。ここに記述した内容はVue.jsを使いこなす上で使用頻度の高い必須な機能なのでVue.jsを使いこなせるようにしっかりと理解しておきましょう。
Vue3ではこれまでのVue2で利用していた記述方法であるOptions APIとVue3から新たに利用できるComposition APIという記述方法があります。本文書はVueのバージョン2を利用して従来のOptions APIを利用した方法で説明を行っています。Vue 2はEOL(End of Life)になったのでこれから学習を開始する人はVue 3を学習してください。そのため新たに本文書のVue 3に対応したVue 3の入門文書を公開しました。Composition APIを利用したい場合は参考にしてください。Vue3でもOptions APIを利用する場合は本文書の内容も十分役に立ちます。
目次
JavaScriptのオブジェクトと関数の短縮
Vue.jsだけではなくフロントエンドに利用されるReactやSvelteなどを理解するためにはJavaScriptのオブジェクトと関数の短縮記述を知っておく必要があります。JavaScriptのオブジェクトはVue.jsを扱う上で必須な知識です。短縮記述はウェブ上で公開されているVueに関する文書で頻繁に使われる記述なのでこちらもしっかりと理解しておいてください。
これらの知識がしっかりと備わっている人は”JavaSrciptのオブジェクト”の章スキップして次の初めてのVueに進んでください。
JavasScriptのオブジェクト
JavaScriptでは、通常の変数は下記のように1つの値を持つことができます。
const person = 'John Smith';
通常の変数とは異なりオブジェクトを利用して複数の値を持つことができる変数で{}を使用して1つの変数に複数の値を持たせることができます。下記のように名前と値を:(コロン)で分けて記述します。名前のことをプロパティと呼びます。
const person = {firstName:"John", lastName:"Smith", age:30};
プロパティの値を取得したい場合は、変数名の後ろ.(ピリオド)とプロパティ名をつけることで取得することができます。firstNameプロパティの値を取得したい場合は、下記のように記述します。
person.firstName
John
上記のオブジェクトの構造はプロパティと値だけのシンプルな構造をしていますがここから少し複雑になってきます。まずJavaScriptのオブジェクトは値だけではなく関数も含めることができます。
下記では、fullNameプロパティに値ではなく関数を割り当てています。
const person = {
firstName: 'John',
lastName : 'Smith',
age : 30,
fullName : function() {
return this.firstName + " " + this.lastName;
}
};
オブジェクトの中の関数はメソッドと呼ばれ下記のように実行することができます。
person.fullName()
John Smith
オブジェクトには値と関数以外にさらに別のオブジェクトを入れることができます。Vue.jsに限らずJavaScriptのオブジェクトを扱う場合は、下記のようなオブジェクトがどのような構造になっているかをすぐに把握できるようになる必要があります。
const person = {
myNumber: 1000,
email: 'john.smith@dev.com',
personalInfo: {
firstName: 'John',
lastName : 'Smith',
age : 30,
fullName : function() {
return this.firstName + " " + this.lastName;
}
}
}
ageの値を取得したい場合は、下記のように記述します。
person.personalInfo.age
30
JavaScriptのオブジェクトを利用するとプロパティによって複数の値を持たせることができます。通常の文字列や数字だけではなく関数もプロパティに設定することができ、プロパティにさらにオブジェクトを持たされネスト構造にすることができることがわかりました。
JavaScriptの関数の短縮
ECMAScript 6で追加された記述方法ですが、オブジェクトの中の関数を短縮系で記述している場合が多いので、新しい記述に慣れていない人はこの機会に慣れておきましょう。先ほど出たpersonオブジェクトのfullNameメソッド部分に注目してください。この記述方法が理解できてないとなんで関数の場合はコロンがないの?という疑問が湧いてくるはずです。
const person = {
firstName: 'John',
lastName : 'Smith',
age : 30,
fullName() {
return this.firstName + " " + this.lastName;
}
}
これまでは下記のように記述しています。
/* ECMAScript6以前の記述方法 */
fullName : function (){
return this.firstName + " " + this.lastName;
}
ECMAScript6の記述では、:(コロン)がなくなりシンプルになっています。
/* ECMAScript6の記述方法 */
fullName(){
return this.firstName + " " + this.lastName;
}
ここまでがオブジェクトと関数の短縮記述の説明です。次からが実際にVueについての説明になります。
はじめてのVue
Vue.jsを使った開発ではVue.jsを利用するためにNode.js環境を構築しnpm, vite(以前はwebpack)を利用して行いますが動作確認のみ行いたい場合や初めてVue.jを使う人はcdnを利用したほうが簡単です。Vue.jsのcdnを利用するために下記のscriptタグを使います。このscriptタグをhtmlファイルに埋め込むことでVue.jsの基本機能を動作確認するための準備は完了です。
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
はじめてのHello World
早速Vue.jsを利用して画面に”Hello World”の文字列を表示させましょう。index.html等任意の名前をつけたhtmlファイルを作成して下記の内容をコピー&ペーストしてブラウザで閲覧するだけです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue</title>
</head>
<body>
<h1 id="app">
{{ message }}
</h1>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello World!'
}
})
</script>
</body>
</html>
ブラウザで確認するとHello World!が表示されます。
“Hello World!”の表示が確認できたら、記述した内容の中身を確認していきましょう。この記述がVue.jsの基本中の基本の形で最初は戸惑うかもしれませんがすぐに慣れるので安心してください。
h1タグにはid=”app”が設定されておりh1タグの中に{{ message }}があります。このmessageの部分がHello World!になっているので、Vue.jsを利用して{{ }}の中のmessageに値が渡されているのではと予想することができます。
<h1 id="app">
{{ message }}
</h1>
scriptタグの中身を見るとVue.jsをmessegeを表示されるために必要な設定が行われています。new VueによりVueインスタンスの作成が行われていますが、Vueインスタンス作成時に elとdataプロパティが入ったオブジェクトが渡されます。これがVue.jsを使う上でもっとも基本になる書式です。
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello World!'
}
})
</script>
new Vueでインスタンスが作成される際に渡されたオブジェクトのelプロパティの値に#appが設定されていますが、この#appがh1タグに付与されていたidのappに対応します。もし、h1のタグのidがrootに設定されているのであれば、このelプロパティの値も#rootにする必要があります。このelを設定することでVue.jsが影響を与えることができるhtml内の範囲が決まります。つまりこのappタグ外にvueに関する処理を設定しても何も起こりません。
dataプロパティにはさらにオブジェクトが渡されておりそのオブジェクトのmessageプロパティの値に”Hello World!”が設定されています。Vue.jsでは、dataプロパティ内にオブジェクトとして、プロパティと値のペアを設定し、htmlに{{ プロパティ名 }}という記述を使うことでその値をブラウザ上に表示させることができます。
{
el: '#app',
data: {
message: 'Hello World!'
}
}
v-textを使用したデータ表示
{{ }}でdataを囲むことでブラウザ上に文字列を表示させることがわかりました。{{ }}ではなくv-textディレクティブを使用しても同様のことを行うことができます。しかし、v-textディレクティブを使用する場合はタグ(ここではspanタグ)が必要となります。
<h1 id="app">
<span v-text="message"></span>
</h1>
spanを追加しましたが、下記のようにdivを追加しid=”app”を設定してh1にv-textを設定することも可能です。<h1>{{ message }}</h1>と表示される内容は同じです。
<div id="app">
<h1 v-text="message"></h1>
</div>
複数の値の設定
dataに設定する値はオブジェクトなのでプロパティと値のペアは1つではなく何個でも追加することができます。message2というもう一つプロパティと値のペアを追加してみましょう。
{
el: '#app',
data: {
message: 'Hello World!',
message2: 'Hello Vue!!',
}
}
htmlにも{{ message2 }}を追加します。
<h1 id="app">
{{ message }}{{ message2 }}
</h1>
ブラウザには、追加したmessage2の値が表示されます。
もし、elで設定したidの#appタグの外に{{ message2 }}を記述したらどうなるかみてみましょう。
{{ message2 }}
<h1 id="app">
{{ message }}
</h1>
#appの外側に記述するとVue.jsの管理下から外れ、通常の文字列として処理されるためブラウザでは下記のように表示されます。{{ message2 }}はVue.jsの管理下から外れるとただの文字列として表示されます。
Vue.jsを使用せずに実行
もしVue.jsを使わなかった場合にJavaScriptだけだとどのように記述するかを見てVue.jsとの違いを確認します。
Javascriptでは、getElementByIdメソッドで要素を取得し、取得した要素に対して文字列の追加を行うことで同じようにHello Worldを表示させることができます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue</title>
</head>
<body>
<h1 id="app"></h1>
<script>
document.getElementById('app').textContent='Hello World';
</script>
</body>
</html>
Javascriptの方法では何かデータを表示させたい場合は必ず要素を指定しなければならず、要素との結びつきがが非常に強固です(getElementByIDで要素を指定)。その反面Vue.jsではvue.jsの管理下におかれたid=”#app”の中であれば要素とは関係なしに表示させたい場所に文字列(data)を配置させることができid=”#app”の中では要素との結びつきが弱くなっています。
とはいえhtmlは要素で構成されているので、Vue.jsでも要素を利用してさまさまな設定を行なっていきます。
タグ属性へのバインド
Vue.jsを使ってブラウザ上にテキストを表示させるためには、HTMLの中で{{ }}を使用することを確認しました。Vue.jsを利用するとタグの属性値の設定も簡単に行うことができます。Vue.jsでは属性を設定するためにv-bindディレクティブを利用します。タグの属性値の設定とはaタグのhrefの設定値をVue.jsで指定するといったものです。
どちらも後ほど説明しますが、最も馴染みのある属性といってもいいstyle属性, class属性はオブジェクトを利用した他の属性とは異なる記述方法で設定を行います。すべての属性が同じ方法で設定できるわけではないとまずは頭の片隅においておいてください。このことがわかっていないと混乱してしまいます。
aタグのhref属性へのバインド
設定したい属性の前に”v-bind:”を挿入してバインドを行います。hrefにバインドする場合は、下記のように記述します。コロンも必須です。プロパティ名はVue.jsのdataの中で設定したプロパティの名前です。プロパティ名を介してhrefに値を設定することができます。
v-bind:href="プロパティ名"
hrefにv-bindディレクティブでバインドすることでhrefはVueの管理下に置かれ、=(イコール)で設定したプロパティ名の値はVueのdataの中で設定したプロパティの値から取得することができます。もし、hrefがv-bindでバインドされなければ、href=”プロパティ名”としてもプロパティ名はただの文字列として認識されます。
hrefの中身をhttps://google.comに設定したい場合は下記のように記述します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>属性へのバインド</title>
</head>
<body>
<h1 id="app">
<a v-bind:href="google">検索エンジン</a>
</h1>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
google: 'https://google.com'
}
})
</script>
</body>
</html>
v-bindを設定したhrefの値にgoogleを設定することで、dataのgoogleプロパティがVueによってhrefのgoogleに渡され、href=”https://google.com”となります。
style属性へのバインド
Vue.jsからstyle属性を設定する方法を2つ紹介します。1つ目は先ほどのhrefと同様の方法でもう一つはオブジェクトを利用した方法です。Vue.jsからのstyle属性の説明を行いますがstyle属性はVue.jsを利用しなくても通常通り利用することは可能です。Vue.jsを利用できるメリットやユーザのインタラクションに合わせて動的にstyle属性を変更できることです。
一つ目の方法はhrefと全く同じ方法で、styleプロパティを介してstyleの値を設定します。
<h1 id="app">
<a v-bind:style="style">検索エンジン</a>
</h1>
var app = new Vue({
el: '#app',
data: {
style: 'font-size:12px;color:red'
}
})
vue.jsで設定した通りにブラウザには12pxの赤い文字が表示されます。
二つ目の方法は、オブジェクトを利用して適用する方法です。しかし、注意点があります。通常CSSでフォントのサイズを設定する時はCSSプロパティfont-sizeを使用します。vue.jsのオブジェクトを利用したv-bindではfont-sizeではなくキャメルケースfontSizeに変更して記述する必要があります。そのままfont-sizeと記述するとVueが認識することができません。
オブジェクトとして適用するので、プロパティと値は:(コロン)で区切り、他のプロパティとは”,(コンマ)”で区切ります。CSSのプロパティの区切り文字の”;(セミコロン)”ではないので記述間違いに注意してください。
<h1 id="app">
<a v-bind:style="{fontSize: applyFontSize, color:fontColor }">検索エンジン</a>
</h1>
applyFontSize、fontColorはVueのdataの中で行います。
var app = new Vue({
el: '#app',
data: {
applyFontSize: '12px',
fontColor: 'red'
}
})
また下記のようにstyle側にはプロパティ名を入れてdata側でオブジェクトを使ってCSSを記述することも可能です。こちらのほうが実践的で複数のCSSのプロパティを適用したい場合はすっきりとわかりやすく記述することができます。
<h1 id="app">
<a v-bind:style="styleObject">検索エンジン</a>
</h1>
var app = new Vue({
el: '#app',
data: {
styleObject: {
fontSize: '12px',
color: 'red'
}
}
})
class属性へのバインド
class属性もstyle属性と同様にオブジェクトを利用して設定することができますが、設定方法が全く異なり設定方法も複数存在します。
下記のように記述しますが、プロパティ名の値はtrue, falseに限ります。trueであれば指定したクラス名が適用され、falseであればクラス名は適用されません。class属性では、要素に対してクラスの適用、非適用を切り替えることができます。
v-bind:class="{クラス名: プロパティ名 or (ture or false)}"
適用するclassはstyleタグ(<style></style>)の中に追加します。classのactiveをh1タグに適用したい場合はactiveの値をtrueに設定します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>属性へのバインド</title>
</head>
<style>
.active{
color: #fff;
background-color: red;
}
</style>
<body>
<div id="app">
<h1 v-bind:class="{active: true}">class属性へのバインド</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
}
})
</script>
</body>
</html>
activeの値がtrueに設定させれているのブラウザでは以下のようにstyleタグの中に設定したclassが適用されていることを確認することができます。
下記のようにtrueをfalseに変更するとh1に対してactive classは適用されません。
<div id="app">
<h1 v-bind:class="{active: false}">class属性へのバインド</h1>
</div>
直接activeの値をtrue, falseを設定していますが、Vueのdata内のプロパティ(isActive)を使用して切り替えることも可能です。
<div id="app">
<h1 v-bind:class="{active: isActive}">class属性へのバインド</h1>
</div>
classの適用、非適用を決めるisActiveプロパティは、true, falseの2つの値のどちらかしか取れません。
var app = new Vue({
el: '#app',
data: {
isActive: true
}
})
1つのclassの適用・非適用の方法はわかりました。1つの要素に対して複数のclassの適用、非適用を行いたい場合は下記のように記述します。isActive、hasErrorプロパティはVueのdataで設定を行い、true, falseどちらかの値をとります。
<div id="app">
<h1 v-bind:class="{active: isActive, error: hasError}">class属性へのバインド</h1>
</div>
var app = new Vue({
el: '#app',
data: {
isActive: true,
hasError: false
}
})
1つのclassに対して1つのデータプロパティが対応していましたが複数のclassに対して1つのデータプロパティが対応する場合は下記のように記述することができます。activeとitalicはclassでisActiveはデータプロパティでtrueかfalseが入ります。
<h1 v-bind:class="{'active italic' : isActive}">
class属性へのバインド
</h1>
class属性のバインドに複数のclassを設定できるだけではなくバインドしないclassも設定を行うことができます。
<h1 class="border-b px-2" v-bind:class="{'active italic text-lg font-bold' : isActive}">
class属性へのバインド
</h1>
style属性と同様にdata内で複数のclassを設定することもできます。
<div id="app">
<h1 v-bind:class="classObj">class属性へのバインド</h1>
</div>
var app = new Vue({
el: '#app',
data: {
classObj:{
active : true,
error: true
}
}
})
これまではclassへのv-bindの設定は真偽値(ture or false)を使って行うことだと説明を行ってきましたが真偽値とは関係なしで要素にclassを設定することができます。その場合は配列を使用します。
<div id="app">
<h1 v-bind:class="[isActive, hasError]">class属性へのバインド</h1>
</div>
var app = new Vue({
el: '#app',
data: {
isActive: 'active',
hasError: 'error'
}
})
変数の値によって適用するClassを分けたい場合は下記のように記述することで実現することができます。showがturnの時はw-32が適用され、falseの場合はw-20が適用されることになります。
<div class="h-screen" :class="[show ? 'w-52' : 'w-20']">
以下のように記述することも可能です。
<div class="h-screen" :class="show ? 'w-52' : 'w-20'">
if文による表示/非表示の切り替え
v-ifによる表示の切り替え
vue.jsではif文を使用することで画面への表示、非表示を制御することができます。vue.jsはifの頭にv-が付きv-ifと記述が変わり名前はv-ifディレクティブと呼ばれます。通常のifと同じで条件によって分岐させることができます。分岐に関するディレクテイブはv-if, v-else, v-else-ifです。
記述は下記の通りです。
<要素 v-if="条件式">コメント</要素>
<要素 v-else-if="条件式">コメント</要素>
<要素 v-else>コメント</要素>
要素にpタグを使い条件式を入れた例です。
<p v-if="stock_number > 0">販売中です。</p>
<p v-else>在庫切れのため販売していません。</p>
stock_numberは、data内のstock_numberの値を変更することで表示する内容を切り替えることができます。0にすると”在庫切れのため販売していません”のみ表示されます。stock_numberを0以上に設定すると”販売中です”に変わります。
var app = new Vue({
el: '#app',
data: {
stock_number: 0
}
})
v-showによる表示の切り替え
表示/非表示に切り替える方法はv-ifディレクティブの他にv-showディレクティブがあります。v-ifの場合条件に合わない場合はv-elseで別の表示を行うことができます。しかしv-showは条件によって表示させるかさせないかの切り替えしかありません。
<要素 v-show="条件式">コメント</要素>
v-showの場合、在庫が0以上の場合は販売中と表示されますが、0の場合は何も表示されません。
<p v-show="stock_number > 0">販売中です。</p>
v-ifとv-showの使い分け
v-showは条件が合わない場合は、displayプロパティがnoneになっているだけなのでブラウザに見えないだけで要素は作成され存在はしています。しかし、v-ifの場合は、条件が一致しなければ要素は作成されないのでその要素は存在しません。ブラウザ描写中に頻繁に表示/非表示を切り替える場合はv-show を使い、表示/非表示を切り替えないがほとんどない場合はv-ifを使用します。displayのnoneとblockの切り替えは要素の作成や削除に比べてコスト(負荷)が少ないためです。要素が作成される作成されないといった要素の存在はブラウザの開発ツールの要素を使って実際に目で確認することができます。
複数の要素の表示/非表示
先ほどのv-ifの書式では1つの要素毎にv-ifの設定を行っていましたが、templateタグを使用すると複数の要素を一括で表示/非表示を切り替えることができます。templateタグはブラウザには表示されないタグです。
<template v-if="stock_number > 0">
<p>販売中です。</p>
<p>まだ在庫は{{ stock_number }}あります。</p>
</template>
stock_numberが1以上であれば販売中です。まだ在庫はXありますと表示されます。0だと何も表示されません。v-ifだけではなくv-showでも利用できます。またv-elseもtemplateタグで利用することができます。
リストの表示
配列のようなリスト構造を持つものは、v-forディレクティブを利用してhtmlの中で展開することができます。JavaScriptのfor文と仕組みは同じです。
データベースから取得したデータやAPIを経由で取得したデータはv-forを利用して展開を行うため、使用頻度の高いディレクティブです。
記述は下記の通りです。
<要素 v-for="変数 in リストの変数">.....</要素>
シンプルな配列のリスト表示
実際にvue.jsを利用してリストの表示を行います。リストにはシンプルな配列を利用しています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>リストの表示</title>
</head>
<style>
</style>
<body>
<div id="app">
<ul>
<li v-for="friend in friends">{{ friend }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
friends: ['Ken','Mike','John','Lisa']
}
})
</script>
</body>
</html>
ブラウザで確認するとv-forにより配列が展開され個別に表示されます。
配列+オブジェクトのリスト表示
先ほどはシンプルな配列でしたが、実際に運用(データベースから取得したものを利用する)ではシンプルな配列ではなくより複雑なデータをリスト表示する必要がでてきます。今回は下記のようなusers配列を使います。配列ですが、各要素にはオブジェクトが入っています。
var app = new Vue({
el: '#app',
data: {
users: [
{id: 1, name:'Ken', age: 20},
{id: 2, name:'Mike', age: 23},
{id: 3, name:'John', age: 21},
{id: 4, name:'Lisa', age: 20},
]
}
})
リストで表示する際は下記のようにして表示することができます。
<ul>
<li v-for="user in users">{{ user.name }}({{ user.age }})</li>
</ul>
ブラウザで確認すると配列要素が表示されます。
配列のキーも同時に出力させたい場合は、下記のように記述すれば配列のキーも取り出すことができます。user, indexについては任意の名前をつけることができます。今回の例ではusers配列を使っているのでuserとしています。
<ul>
<li v-for="(user,index) in users">{{ index }} {{ user.name }}({{ user.age }})</li>
</ul>
オブジェクトinオブジェクトのリスト表示
先ほどは配列の要素にオブジェクトが入ってましたが、今回はオブジェクトの中にオブジェクトが入っている場合です。
var app = new Vue({
el: '#app',
data: {
users: {
'Ken': {
age: 20,
email: 'ken@gmail.com'
},
'Mike': {
age:23,
email: 'mike@yahoo.com'
},
'John': {
age:21,
email: 'john.doe@example.com'
},
'Lisa': {
age:20,
email: 'lisa@google.com'
}
}
}
})
<ul>
<li v-for="(user,name,index) in users">{{ name }} {{ user.email }}({{ user.age }})</li>
</ul>
user, name, indexと指定することで0から振られた番号も取得することができます。下ではindexの画面表示は行っていませんが{{ index }}で表示させることが可能です。
v-forを実行する際にv-bind:keyの設定を行います。なぜv-bind:keyを設定するのかを知りたい場合は下記の文書が参考になります。
vue.jsを利用したフォームの入力
ユーザがinput要素の入力フォームに入力した内容をVue.jsで設定したデータプロパティと結びつけることができます。つまり入力した値が即時にVue.js内に設定したデータプロパティに反映されます。
input要素での動作確認
テキスト入力のinput要素を使って動作確認を行います。フォーム入力内容とvue.jsを結びつけるために、v-modelディレクティブを使用します。
<input type="text" v-model="textInput">
v-modelに指定したtextInputをvue.jsのdataに設定し、初期値を””(ブランク)とします。
var app = new Vue({
el: '#app',
data: {
textInput: '',
}
})
画面上には、テキストの入力エリアが表示されます。この状態では入力をしても画面にテキストエリアに入力した文字が表示されるだけでそれ以外は何も変化がありません。
入力した内容を見るためにvue.jsのdataであるtextInputプロパティを画面に表示させる必要があります。{{ textInput }}をhtmlの中に埋め込みます。
<input type="text" v-model="textInput">
<p>{{ textInput }}</p>
入力フォームにテキストを打ち込むと入力した内容がそのままフォームの下に表示されます。このようにv-modelを使用することで入力したデータが即座にdataのtextInputに反映され、そのデータをリアルタイムにブラウザ上に表示できることがわかります。
通常のinput要素の場合はvalueに値を設定するとその値がinput要素に入った状態で表示されます。しかし、v-modelではvalue値を事前に入力してもvalueに設定した値はブラウザには表示されません。初期値をinput要素に入れておくためには、valueではなくdataのtextInputの値を設定しておく必要があります。
var app = new Vue({
el: '#app',
data: {
textInput: '初期値はここに入れておく',
}
})
その他の要素については下記の文書を参考にしてください。
イベントの設定方法
JavaScriptではユーザとのインタラクティブを実現するため、ユーザがブラウザ上のボタンをクリックする、ある要素の上をマウスを通過させる、キーをアップする等のイベントを監視することで、そのイベントをトリガー(きっかけ)として別の処理を行うことができます。vue.jsではv-onディレクティブを使用して、イベントを監視してイベントに対する別の処理(メソッド)を行います。
記述は下記のとおりです。
<要素 v-on:イベント名="メソッド名">....</要素>
メソッド名は実行したい処理の関数名です。Vueインスタンスにmethodsプロパティを追加することで設定を行います。イベント名はclick, blur, keyup等のユーザの処理に関する名前が割り振られているのでその名前を使用します。
var app = new Vue({
el: '#app',
data: {
},
methods: {
'メソッド名': function(){
// 処理の中身
},
'メソッド名': function (){
// 処理の中身
}
}
})
//別の記述方法
var app = new Vue({
el: '#app',
data: {
},
methods: {
'メソッド名'(){
// 処理の中身
},
'メソッド名'(){
// 処理の中身
}
}
})
イベント名には、click以外にもmouseover, submit等さまざまなものがあります。
vue.jsでのイベントの基本を理解するためにbuttonをクリックするとブラウザにメッセージを表示させるイベント処理を行います。
button要素をクリックした後に処理を行わせるため、v-onの後ろにはイベント名であるclickを指定します。メソッド名はclickButtonとします。ボタンがクリックされたらclickButton関数が実行されるように設定しています。
<div id="app">
<button v-on:click="clickButton">ボタン</button>
</div>
メソッド名は、vue.jsにmethodsオブジェクトを追加し、clickButtonプロパティとして登録を行います。clickButtonプロパティには関数を設定します。
var app = new Vue({
el: '#app',
data: {
},
methods:{
//clickButton(){
clickButton : function (){
alert('Click Button')
}
}
})
buttonを押すとclickイベントが発生し、vue.jsでそのclickイベントを検知し、clickButtonメソッドが実行され、alertメッセージが表示されます。ブラウザ上に下記のメッセージが表示されれば、vue.jsのイベント処理は正常に動作しています。
class属性のv-bindとの組み合わせ
前の章では、class属性にv-bindを設定することで、要素へのclassの適用/非適用を切り替えることを学びました。clickイベントと組み合わせることでclassの適用/非適用を切り替えることができます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>イベント処理</title>
</head>
<style>
.active{
background-color: red;
color:white;
}
</style>
<body>
<div id="app">
<h1 v-bind:class="{active: isActive}">Hello World</h1>
<button v-on:click="classToggle">ボタン</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
isActive: true
},
methods:{
classToggle : function (){
this.isActive = !this.isActive
}
}
})
</script>
</body>
</html>
styleタグでactiveクラスを設定し、activeクラスが適用された要素は、背景が赤で文字が白になる設定を行っています。
<style>
.active{
background-color: red;
color:white;
}
</style>
htmlの部分では、h1要素でclass属性にv-bindを設定することでisActiveプロパティがtrueの時には、activeクラスが適用され、falseの時には適用されません。
button要素にv-onディレクティブでclickイベントを監視することで、buttonがクリックされれるとclassToggleメソッドが実行されます。
<div id="app">
<h1 v-bind:class="{active: isActive}">Hello World</h1>
<button v-on:click="classToggle">ボタン</button>
</div>
JavaScriptのVueの内部のプロパティでは、dataオブジェクトにisActiveプロパティを追加し、初期値はtrueに設定しています。methodsオブジェクトにclassToggleメソッドを追加し、isActiveの真偽を逆にする処理を設定しています。this.が付いているは、メソッドが設定されているのと同じVueインスタンス内にあるdataオブジェクトのisActiveを使用しているためです。
var app = new Vue({
el: '#app',
data: {
isActive: true
},
methods:{
classToggle : function (){
this.isActive = !this.isActive
}
}
})
ここまで理解できたらブラウザを使って動作確認を行いましょう。buttonをクリックする毎に背景色と文字の色が変わることが確認できます。
データを利用する処理(算出プロパティ)
Vueの中に保存されているdataを利用して別の処理を行うことができます。データを使って処理する(=計算する)のでcomputedプロパティと呼ばれます。中身は関数で、日本語では算出, 算術プロパティと訳されるようです。
税込価格を自動で計算する
税抜価格から税込価格を表示する方法を算出プロパティを利用して行います。Vueのdataの値を元に計算を行います。以下がコードです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>算出プロパティ</title>
</head>
<body>
<div id="app">
<p>税抜価格: ¥{{ no_tax_price }}</p>
<p>税込価格: ¥{{ include_tax_price }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
no_tax_price: 100
},
computed:{
include_tax_price : function (){
return this.no_tax_price*1.1
}
}
})
</script>
</body>
</html>
中身を確認していくとhtmlの部分では、{{ }}を利用してVueのdataのno_tax_priceを表示しています。その下に同じように {{ }}を利用してinclude_tax_priceを表示させていますが、Vueのdataの中では、no_tax_priceしか設定していないのでデータプロパティではありません。include_tax_priceは算出プロパティですが、dataのように扱えるため({{ }}で囲めば中身が表示される)htmlを見ただけではdataか算出プロパティか区別がつきません。
<div id="app">
<p>税抜価格: ¥{{ no_tax_price }}</p>
<p>税込価格: ¥{{ include_tax_price }}</p>
</div>
Vueの処理部分を見るとVueに算出プロパティが追加され、先ほどのinclude_tax_priceが登録されています。dataのようにhtml上では見えているinclude_tax_priceは算出プロパティで実際はno_tax_priceを利用して消費税計算を行っています。
var app = new Vue({
el: '#app',
data: {
no_tax_price: 100
},
computed:{
include_tax_price : function (){
return this.no_tax_price*1.1
}
}
})
ブラウザ上では以下のように表示されます。
税込価格を1.08倍するのであれば下記のように{{ }}の中で直接計算を行うことも可能です。今回のような簡単な計算式であれば、{{ }}の中で計算を行っても問題になることはありませんが、長い計算式を使う場合や後にコードを読む際に算出プロパティ名に適切な処理名をつけていれば可読性も上がります。
<div id="app">
<p>税抜価格: ¥{{ no_tax_price }}</p>
<p>税込価格: ¥{{ no_tax_price*1.08 }}</p>
</div>
算出プロパティの別の例
他のv-ディレクトリと組み合わせて算出プロパティの理解を深めていきましょう。
input要素に入力する文字数が10文字以上であれば、10文字を超えていることを表示し、10文字より文字数が少ない場合は不足している文字数の数を表示させるプログラムを作成します。
input要素にはv-modelでバインドを行い、文字数の判定はv-ifで行い、不足している文字数は算出プロパティで表示させます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>算出プロパティ</title>
</head>
<body>
<div id="app">
<p>10文字以上の文字列を入力してください。</p>
<input type="text" v-model="inputCharactors">
<p v-if="inputNumber < 10">必要な文字数は{{ needNumbers }}文字です</p>
<p v-else>10文字以上入力されています</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
inputCharactors: ''
},
computed:{
inputNumber : function (){
return this.inputCharactors.length;
},
needNumbers : function(){
return 10 - this.inputNumber;
}
}
})
</script>
</body>
</html>
VueインスタンスにデータinputCharactorsを準備して、v-modelでinput要素の入力値をinputCharactorsと紐付けます。inputフォームに入力した値はリアルタイムでinputCharactorに反映されます。
<input type="text" v-model="inputCharactors">
算出プロパティinputNumberとneedNumbersを追加します。inputNumberプロパティは、データinputCharactorsを利用して文字列の長さを計算します。needNumbersは算出プロパティを利用して残りの文字数を計算します。
computed:{
inputNumber : function (){
return this.inputCharactors.length;
},
needNumbers : function(){
return 10 - this.inputNumber;
}
}
htmlではv-ifを使って条件の判定を行いtrueの場合は、残りの必要な文字列を表示し、falseの場合は、10文字以上入力ができていることを表示させています。
<p v-if="inputNumber < 10">必要な文字数は{{ needNumbers }}文字です</p>
<p v-else>10文字以上入力されています</p>
まだinput要素には何も文字が入力されていない状態です。
文字列を入れるとリアルタイムで必要な文字数の残り文字が表示されます。
10文字以上の文字数を入力すると”10文字以上入力されています”と表示されます。
データを監視する処理
Vueにはデータを監視する機能も備わっています。data, computedプロパティの”値”を監視することができ、設定した条件を満たした場合に別の処理を行うことができます。
count数に変化があると処理を行う
データ監視機能の理解をするために以下のプログラムを作成します。
inputの入力フォームを作成し、ユーザに任意に数字を入力してもらいます。その入力する値に対して監視を行い、入力した数字が10を超えるとコンソールにメッセージを表示させるというものです。
v-modelを設定したシンプルなinput要素を設定します。
<input type="number" v-model="count">
dataプロパティにcountを設定します。追加したこのcountがこのプログラムでの監視対象となるものです。監視を行うためには新たにwatchプロパティをVueに追加する必要があります。watchプロパティの中ではdataプロパティのcountと同じ名前でcountと設定していますが、この名前は監視するdataのcountと同じである必要があるため間違いではありません。
watchプロパティの中で入力した数字が100を超えたら、console.logにメッセージがでるように設定を行っています。
var app = new Vue({
el: '#app',
data: {
count : 0
},
watch: {
count: function(value){
if(value > 100){
console.log('入力値が100を超えました')
}
}
}
})
実際に設定したinputフォームに100を超える値を入力した場合のみコンソールログにメッセージが表示されます。
watchする値について
watch機能では入力した値だけではなく、その一つ前に入力した値も保持することができます。古い値と新しい値を保持したい場合は下記のように関数に2つの引数を取ることができます。新しい値と古い値がコンソールに表示されるので比較することができます。
var app = new Vue({
el: '#app',
data: {
count : 0
},
watch: {
count: function(newCount, oldCount){
console.log('newCount:' + newCount)
console.log('oldCount:' + oldCount)
}
}
})
まとめ
vue.jsを勉強し始めた人が最初に並ぶ基本機能について説明を行いました。まずはこの基本機能を使い方をしっかりと理解した上で、コンポーネントなどの重要な機能を理解していく必要があります。