こんばんは、フリューのジョンです。最近Vue.jsを理解しようとVue.jsのソースコードリーディングをしています。
前回はVue.jsのかんたんな使い方とjQueryとの比較、などをお話しました。
今回はVue.jsの基本の話、elプロパティ、dataプロパティ、methodsプロパティの話をします。
Vue.jsのバージョンは2.3.0です。
elプロパティ
elプロパティはString型、または、HTML Elementである必要があります。
String型で与えた場合、document.querySelectorで存在した要素を使いますので、HTML Elementを与える必要はあまり無いと思われます。
コンパイル対象のルート要素に対して設定します。
コンパイルとは、データのバインディング設定などを行うフェーズです。
Vue.jsではルート要素以下の要素を網羅してHTMLを再構築しています。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>elプロパティについて</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script> <script> window.onload = () => { new Vue({ beforeMount: function() { console.log(document.querySelector('section')); // コンパイル前の要素が取得できる document.querySelector('section').onclick = () => console.log('hi'); // sectionが作り直されるため、ここは呼ばれない }, mounted: function() { console.log(document.querySelector('section')); // コンパイル後の要素が取得できる }, el: '#vue' }); } </script> </head> <body> <section id="vue"> <ul> <!--Vue.jsのfor文--> <li v-for="n in 100">{{n}}</li> </ul> </section> </body> </html>
dataプロパティ
dataプロパティはObject型、または、Object型を返すFunction型である必要があります。
後で説明するコンポーネントを使う場合、dataプロパティはFunction型でなければいけないので、常にFunction型を返すようにしておくほうが妥当だと思われます。
dataプロパティの値にはインスタンスからアクセスすることができます。また、HTML側からは直接アクセスすることが可能です。
さらに、Vue.jsはこのObject型に記述されたプロパティの変更を感知することができます。感知することで画面側の再描画が走ります。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>dataプロパティについて1</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script> <script> window.onload = () => { const vm = new Vue({ data: () => { return { message: 'fuga' } }, el: '#vue' }); setTimeout(() => vm.message = 'hoge', 2000); } </script> </head> <body> <section id="vue"> <!--2秒後にhogeに変わります--> <span>{{message}}</span> <span>{{message + 'aaa'}}</span> </section> </body> </html>
このようにdataプロパティが返すObject型をいじると、再描画されているのがわかります。これは、Vue.jsがプロパティにsetterとgetterをつけており、その中で変更を検知しているためです。
しかし、配列の場合は少し勝手が違います。配列の中身をいじっても更新はされません。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>dataプロパティについて2</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script> <script> window.onload = () => { var vm = new Vue({ data: () => { return { messages: ['hoge', 'fuga', 'piyo'] } }, el: '#vue' }); setTimeout(() => vm.messages[0] = 'ほげ', 2000); } </script> </head> <body> <section id="vue"> <!--ほげに変わらない--> <p>{{messages[0]}}</p> <p>{{messages[1]}}</p> <p>{{messages[2]}}</p> </section> </body> </html>
もしこのような場合があれば次のように置き換えます。
vm.messages[0] = ‘ほげ’ → Vue.set(vm.messages, 0, ‘ほげ’)
またはspliceメソッドを用いてやります(spliceメソッドは再描画の検知ができます)
vm.messages[0] = ‘ほげ’ → vm.messages.splice(0, 1, ‘ほげ’)
(https://jp.vuejs.org/v2/guide/list.html#注意事項)
methodsプロパティ
methodsプロパティはプロパティがFunction型のObject型である必要があります。
methodsの各関数のthisはインスタンスがバインドされていますので、アロー関数を使わないようにしたほうが良いと思われます。
これらの関数にはdataプロパティと同じようにアクセスすることができます。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>methodsプロパティについて1</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script> <script> window.onload = () => { var vm = new Vue({ methods: { test: function() { console.log('hoge') } }, el: '#vue' }); setTimeout(vm.test, 2000); } </script> </head> <body> <section id="vue"> <p>{{test()}}</p> </section> </body> </html>
また、結果を返す関数も記述ができ、内部で使用しているプロパティが変更されると再描画されます。
しかし、この書き方は推奨されていません。全てのmethodsが自分が参照していないプロパティが変更されても、実行をしてしまうためです。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>methodsプロパティについて2</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script> <script> window.onload = () => { var vm = new Vue({ data: () => { return { message01: 'hoge', message02: 'hoge' } }, methods: { test01: function() { console.log('test 01'); return 'Hello : ' + this.message01; }, test02: function() { console.log('test 02'); // message01だけを編集したはずがここが呼ばれている return 'Hello : ' + this.message02; } }, el: '#vue' }); setTimeout(() => vm.message01 = 'fuga', 2000); } </script> </head> <body> <section id="vue"> <p>{{test01()}}</p> <p>{{test02()}}</p> </section> </body> </html>
この問題を解消したい場合はcomputedプロパティを使いましょう。computedプロパティは後々お話します。
まとめ
Vue.jsの基本のプロパティの紹介とその使い方をご紹介しました。
次回は、HTML側について詳しく紹介したいと思います。
ありがとうございました。