見出し画像

Vue.js勉強記録その6 コンポーネントを使おう section3-2 ver3

こちらの書籍で勉強中。

今回でsection3-2を終わらせます!

■v属性を使いこなす

・イベント処理とmethods

前回は、クリックに対してイベントを設定しました。

今回は、inputタグに数字が入力された時のイベント処理です。

<h1 class="bg-secondary text-white display-4 px-3">Vue3</h1>
<div id="app" class="container">
   <p>{{message}}</p>
   <hello />
</div>

<script>
   const appdata = {
       data() {
           return {
               message: '※コンポーネントを表示する',
           }
       }
   }
   let app = Vue.createApp(appdata);

   app.component('hello', {
       data() {
           return {
               num: 0,
               message: 'type a number'
           }
       },
       methods: {
           calc() {
               var total = 0;
               for (var i = 1; i <= this.num; i++) {
                   total += i;
               }
               this.message = "total: " + total;
           }
       },
       template: `
           <div>
               <p class="alert alert-info h4">{{message}}</p>
               <div>
                   <input class="form-control" type="number" v-on:input="calc" v-model="num">
               </div>
           </div>
           `
   });

   app.mount('#app');
</script>

inputに、v-onでイベントが設定されている。何気にoninputというイベントを初めて知った。

インプットの値が変更されると、calcメソッドが実行される。
また、v-model="num"の記述により、dataメソッド内のnumの値が変わる

calcメソッドは、変数totalを作成し、dataメソッド内のnumの回数分繰り返し処理を行なっている。繰り返し処理自体は、いわゆる等差数列の足し算ですね。

最後に、足し算が終わったデータをつかって、dataメソッド内のmessageに文字列を代入している。

その後、そのmessageが、pタグの中の、{{message}}の記述により、出力される。


・算術プロパティについて

次は、算術プロパティなるものの紹介。

算術プロパティとは、計算できるプロパティと紹介されている。

computed:{
    名前(引数){処理},
    名前(引数){処理},
    ...
}

こんな感じで、コンポーネント内に記述する。

一つ前のコードと、全く同じ様に動く、別の書き方を紹介している。

<h1 class="bg-secondary text-white display-4 px-3">Vue3</h1>
<div id="app" class="container">
   <p>{{message}}</p>
   <hello />
</div>

<script>
   const appdata = {
       data() {
           return {
               message: '※コンポーネントを表示する',
           }
       }
   }
   let app = Vue.createApp(appdata);

   app.component('hello', {
       data() {
           return {
               num: 0,
               message: 'type a number'
           }
       },
       computed: {
           calc: (e) => {
               let total = 0;
               for (let i = 1; i <= e.num; i++) {
                   total += i
               }
               return 'total: ' + total
           }
       },
       template: `
<div>
<p class="alert alert-info h4">{{calc}}</p>
<div>
   <input class="form-control" type="number" v-model="num">
</div>
</div>
`
   });

   app.mount('#app');
</script>

最初にコードだけ見た時は、calcの関数を実行する処理が書かれていなそうに見えて、動くのかな?と思ったけど、ブラウザで表示すると問題なく動いた。一瞬「??」となったけど、テキストを読み進めると納得できた。

イベントは、ユーザーの動作(クリックやinputの変更)に対して実行するのに対して、算術プロパティは、「依存する値」が更新された時に実行するとある。

つまり、今回の場合は、calcの中で使われている、numの値が変わるとcalcが実行されるらしい。

なお、このコードは少しテキストから変えてみた。

calc:function(event){処理}

になっているけど、アロー関数にしてみた。(イベントオブジェクトもeにしてみた)

calc:(e)=>{処理}

この場合、this.numで取れていた値が、e.numにしないと取れなかった。thisをconsole.logで出力したら、windowだった。この辺は、普通のjsと同じらしい。

依存する値が変わると、勝手にメソッドが実行されるって、なんかすごい。sassのwatchみたいと思ったw


・ローカルコンポーネント

変数と同じ様に、コンポーネントにもローカルやグローバルの考え方があるらしい。

ローカルコンポーネントの書き方は、こんな感じ

components:{
    名前:{内容}
    名前:{内容}
    名前:{内容}
    ・・・
}

詳しい話は、テキストを読んでもちゃんとはわからなかったが、要するに過不足が少なくするにはローカルのが良いよという認識で、とりあえず先に進むw

<h1 class="bg-secondary text-white display-4 px-3">Vue3</h1>
<div id="app" class="container">
   <p>{{message}}</p>
   <div><hello /></div>
   <div><hello /></div>
   <div><hello /></div>
</div>

<script>
   const appdata = {
       data() {
           return {
               message: '※コンポーネントを表示する',
           }
       },
       components: {
           hello: {
               data() {
                   return {
                       counter: 0
                   }
               },
               template: `<p v-on:click="counter++" class="alert alert-info h5">clicked:{{counter}}.</p>`
           }
       }
   }
   let app = Vue.createApp(appdata);
   app.mount('#app');
</script>

これで、pタグをクリックすると数字が1ずつ増えていくテンプレートが出来る。

<hello />が3つあるので、3個同じものが出来る。

このコードを見た時に、クリックに対してのメソッドが書かれていなくて、一瞬「??」となったが、よく見れば、v-on:click="counter++"と、属性の中に処理が書かれていた。。。基本大事。

<div><hello /></div>が、三つあるが、divタグを取ってしまうとなぜか一つしか出力されなかった。これはvue.jsの仕様?それともbootstrapの仕様?

試しに以下の様なコードを書いてみた。

<p class="alert alert-info h5">おはようございます</p>
<p class="alert alert-info h5">こんにちは</p>
<p class="alert alert-info h5">こんばんは</p>

<div><p class="alert alert-info h5">おはようございます</p></div>
<div><p class="alert alert-info h5">こんにちは</p></div>
<div><p class="alert alert-info h5">こんばんは</p></div>

今回使っている、テンプレートの中身から、vueっぽい記述のみを消して、HTMLを書いてみたら、divで括っても括らなくても関係なく普通に表示されたので、<hello />をdivで括らないと一つしか出てこないのは、きっとvueの仕様で良いのかな?

はっきりわからないが、とりあえずいつかわかるだろうということで、そういうもんだと思っておく。


■まとめ

今回で、ようやくsection3-2が終わりです。長かったw

やっぱりイベントが出てくると楽しいですね。

次からは、プロジェクトになる様子。引き続き頑張ります!

この記事が気に入ったらサポートをしてみませんか?