Vue.jsはJavaScriptフレームワークのひとつです。JavaScriptによりページの書き換えを実現し、ユーザーの操作に応じた動的なウェブアプリケーションの開発ができます。
Hello, Vue 3
プログラミング入門書なら最初に必ずある「Hello World」をやってみます。
マスタッシュ構文とはVueの構文で使われる{{}}のことです。形状が口髭(英語ならmoustache)に似ているためこのような名前が作られました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>はじめてのVue 3</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.jsdelivr.net/npm/vue@3.2/dist/vue.global.js"></script> </head> <body> <h1>Hello, Vue 3</h1> <div id ="ex1"> <p><span>{{text}}</span> (基本)</p> <p><span v-text="text"></span> (v-text でマスタッシュ構文のかわりになる)</p> <p><span v-pre>{{text}}</span> (v-preをつけることでマスタッシュ構文を無効化できる)</p> </div> <p>{{text}} (id ="ex1"の外では意味をなさない)</p> <script> Vue.createApp({ data: function() { return { text: 'Hello, Vue 3', }; }, }).mount('#ex1'); </script> </body> </html> |
マスタッシュ構文はmount(‘#ex1’)としている以上、id =”ex1″のタグ内でないと効果はありません。
で、なにが便利なのか?
以下は普通のJavaScriptで書かれたコードですが、表示されるtextを変更するためにはtextの値を変更するだけではダメで、その都度innerTextにtextを設定しなければなりません。ところがvue3であれば値を変更するだけで反映されるようになるのです。
1 2 3 4 5 6 7 8 9 10 |
<div id="legacy"></div> <script> let text = 'aaa'; let $el = document.getElementById('legacy'); $el.innerText = text; text = 'bbb'; // textを変更するだけでなく $el.innerText = text; // この処理が必要! </script> |
v-bindでHTMLの属性を変更する
v-bindを使えば作成した変数の値をHTMLの属性に渡すことができます。上ふたつはリンクのリンク先urlとアンカーテキストを設定しています。最後の例ではボタンの有効無効を指定しています。後述するイベント処理を使えば、これらを動的に変更することができるのです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div id ="ex2"> <p><a v-bind:href="url">{{sitename}}</a></p><!-- v-bindでhref属性に文字列を指定できる --> <p><a :href="url">{{sitename}}</a></p><!-- v-bindは省略できる --> <input type="button" value="ボタンは無効化される" :disabled="flag"> </div> <script> Vue.createApp({ data: function() { return { url: 'https://lets-csharp.com/', sitename: '鳩でもわかるC#', flag: true, }; }, }).mount('#ex2'); </script> |
双方向データバインディング
双方向データバインディングとはデータあるいは対象の変更を自動的にもう一方に反映(同期)することを、双方向で実現する仕組みのことです。
普通のJavaScriptだとテキストボックス内のデータを取得して表示させようとするとテキストボックス内の文字列取得の処理とdiv要素への文字列の設定というふたつの作業が必要です。vue3はこれを自動化してくれるのです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<style> .w300 { width: 300px; } </style> <div id="legacy3"> <input type="text" class = "w300" id="textbox1"><br> <input type="text" class = "w300" id="textbox2"><br> <button onclick="click1()">反映</button> <div id="result1"></div> <div id="result2"></div> </div> <script> let $text1 = document.getElementById('textbox1'); let $text2 = document.getElementById('textbox2'); let $result1 = document.getElementById('result1'); let $result2 = document.getElementById('result2'); function click1(){ $result1.innerText = $text1.value; $result2.innerText = $text2.value; } </script> |
vue3だとテキストボックス内の文字列が変わるとすぐに変更が反映されます。テキストボックス同士の同期も可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div id ="ex4"> <div><input type="text" v-model="text" class="w300"></div> <p>{{text}}</p> <!-- テキストボックス同士の同期も可能 --> <div><input type="text" v-model="text" class="w300"></div> </div> <script> Vue.createApp({ data: function() { return { text: 'テキストを変更してください', }; } }).mount('#ex4'); </script> |
v-modelのあとに.trimをいれると前後の空白を除去した状態で同期されます。.numberなら数値のみを扱います。.lazyだと編集時にただちに同期するのではなく、フォーカスが外れたときに同期されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<style> .mb20 { margin-bottom: 20px; } </style> <div id ="ex5"> <div class="mb20"> <input type="text" v-model.trim="text1" class="w300"><br> 前後の空白を除去:{{text1}} </div> <div class="mb20"> <input type="text" v-model.number="text2"><br> 数値に変換された結果:{{text2}} </div> <div class="mb20"> <input type="text" v-model.lazy="text3" class="w300"><br> 編集後フォーカスを外れたときに同期される:{{text3}} </div> </div> <script> Vue.createApp({ data: function() { return { text1: 'テキストを変更してください', text2: '0', text3: 'テキストを変更してください', }; }, }).mount('#ex5'); </script> |
複数の属性の変更
複数の属性を同時に変更することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<div id ="ex6"> <p><a v-bind="attrs1">リンク</a></p><!-- urlとアンカーテキストを変更する --> <p v-bind:style="styles1">30px 赤色で描画</p><!-- 複数のstyle属性を変更する --> </div> <script> Vue.createApp({ data: function() { return { attrs1:{ innerText: '鳩でもわかるC#', href:'https://lets-csharp.com/', style:'font-weight:bold', }, styles1:{ 'font-size':'30px', 'font-weight':'bold', 'color':'#f00', }, }; }, }).mount('#ex6'); </script> |
イベントハンドラ
最初の例は、マウスが要素内に入るとMouseEnterが、出るとMouseLeaveが呼び出され、要素内の文字列が変わるようにしています。2つ目の例はボタンをクリックするとクリックした回数が表示されます。ただし右のボタンは1回しか反応しません。3つ目の例はボタンをクリックすると文字が大きくなっていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
<style> .area { width: 200px; height: 70px; border: 1px solid #000; } </style> <div id ="ex7"> <div class = "area mb20" v-on:mouseenter="MouseEnter" v-on:mouseleave="MouseLeave">{{text}}</div> <!-- マウスが要素内に入るとMouseEnterが、出るとMouseLeaveが呼び出される --> <div class="mb20"> <button v-on:click="Click">カウントアップ</button> <button v-on:click.once="Click">カウントアップ(1回だけ)</button><br> <!-- v-on:click.once とすると1回しか実行されない --> {{count}} </div> <div class="mb20"> <button v-on:click="ChangeFontSize">文字を大きくする</button> <p v-bind:style="styles1">赤色で描画</p> </div> </div> <script> Vue.createApp({ data: function() { return { text: 'None', count:0, styles1:{ 'font-size':'14px', 'color':'#f00', }, fontSize : 14, }; }, methods:{ MouseEnter(){ this.text = 'MouseEnter!!'; }, MouseLeave(){ this.text = 'MouseLeave!!'; }, Error(){ this.text = 'error!!'; }, Click(){ this.count++; }, ChangeFontSize(){ this.fontSize += 2; this.styles1['font-size'] = this.fontSize + 'px'; } } }).mount('#ex7'); </script> |