「Vue.js」の「コンポーネント」の仕組みを学ぶ
今回は「Vue.js」の「コンポーネント」について学んでいきたいと思います。
「Vue.js」は「あらかじめ用意されている仕組み」を「どのように組み合わせて利用していくのか?」を考えていくことが重要だと思い始めています。
まだまだ「学ぶべき内容」は多いので、「Vue.jsプログラム」を書きながらマイペースで学んでいきたいと思います。
「コンポーネント」の仕組み
「コンポーネント」はいろいろなドキュメントを読んでいる中でその考え方に触れたことがあるのですが、具体的にどのように「コンポーネント」を利用していくのかはわかりませんでした。
「コンポーネント」はその文字通り「WEBページ」の「構成部品」ですが、「コンポーネント」を作成することで、さまざまな箇所で「コンポーネント」を再利用することができます。
「Vueコンポーネント」のイメージを作成してみると、
のようになります。
1つの「Vueコンポーネント」がさまざまなページで再利用されています。
もし、「Vueコンポーネント」の内容に変更があれば、「Vueコンポーネント」を1つだけ修正すれば他のページの「Vueコンポーネント」の内容も自動で変更されます。
「コンポーネント」を使う最大とも言えるメリットはここにあるのでは無いかと思っています。
「コンポーネント」は「Vue.js」だけの機能ではありません。
「Webコンポーネント」など他の技術を利用して同様の仕組みを利用することもできます。
「Vue.js」の「コンポーネント」の作り方
それでは早速シンプルな「コンポーネント」を作ってみたいと思います。
Vue.component
「コンポーネント」の作り方は複数あり、はじめに「Vue.component」を利用した作り方を学んでいきたいと思います。
「コンポーネント」の定義方法は下記のようになります。
Vue.component('コンポーネント名', { コンポーネントの内容 })
ボタンを1つ表示する「シンプルなコンポーネント」を作成してみると、
<div id="app"> <alert-button></alert-button> </div> <script> Vue.component('alert-button', { template: '<button>ALERT BUTTON</button>' }) let app = new Vue({ el: '#app' }) </script>
のようになります。
このプログラムを実行すると、
のようになります。
コンポーネント名は「alert-button」に設定し「template」に「ボタンのHTML要素」を記述しています。
コンポーネント名は「カスタムタグ」と呼ばれる独自の「HTMLタグ」となるため、HTMLには、
<alert-button></alert-button>
のように「カスタムタグ」を記述していきます。
「コンポーネントの内容」には、他にもこれまでに学んできた、
- data
- computed
- methods
- filter
- props
- ライフサイクルフック
を定義することもできます。
「dataプロパティ」を定義する際には
data: { number: 0 }
のようなこれまでの定義方法が使えません。
必ず、
data: { function () { return { number: 0 } } }
のように「関数」を定義する必要があります。
親子関係を持つ「コンポーネント」
「コンポーネント」は「親子関係」を持つことができます。
プログラムを作成してみると、
<div id="app"> <parent-comp></parent-comp> </div> <script> Vue.component('child-comp', { template: '<div><p>子のコンポーネントです。</p></div>' }) Vue.component('parent-comp', { template: '<div>親のコンポーネントです。<child-comp></child-comp></div>' }) let app = new Vue({ el: '#app' }) </script>
のようになります。
このプログラムを実行すると、
のようになります。
「child-comp」が「子のコンポーネント」で、「parent-comp」が「親のコンポーネント」です。
「parent-comp」の「template」の中で「child-comp」が利用されていますね。
このようにある「コンポーネント」の中で、別の「コンポーネント」を利用すると「親子関係」が作られます。
子コンポーネントへ値を渡す方法
「props」を利用すると「親コンポーネント」から「子コンポーネント」に値を渡すこともできます。
プログラムを作成してみると、
<div id="app"> <parent-comp></parent-comp> </div> <script> Vue.component('child-comp', { props: ['data'], template: '<div><p>子のコンポーネントです。親コンポーネントから受け取ったデータは「{{ data }}」です。</p></div>' }) Vue.component('parent-comp', { template: '<div>親のコンポーネントです。<child-comp data="sample_data"></child-comp></div>' }) let app = new Vue({ el: '#app' }) </script>
のようになります。
このプログラムを実行すると、
のようになります。
「子コンポーネント」で「props」を定義し、「親コンポーネントのtemplate」に「子コンポーネントのカスタム属性」を定義し「値」を渡しています。
この仕様を理解するまでしばらく時間を要しました。
慣れるしかなさそうですが、まだ何か理解ができている感覚が無いため、何回か学習していく必要がありそうです。
「1つのデータ」を渡しても実用的にあまり使えないため「APIから受け取ったJSON」をパースして配列で渡す方が実用的になりそうですね。
「Vue.component」で作成したコンポーネントは「グローバルコンポーネント」として登録されているため、全ての「Vueインスタンス」の「template」内で利用することができます。
ではあるコンポーネントでしか利用できない「ローカルコンポーネント」を作成するにはどうすればいいのでしょうか?
「ローカルコンポーネント」の作り方
「ローカルコンポーネント」は「componentsプロパティ」に「コンポーネント」を登録することで、その「Vueインスタンス」内でのみ「コンポーネント」を利用することができます。
プログラムを作成してみると、
<div id="app"> <button-component></button-component> </div> <script> const buttonComponent = { template: '<button>ボタン</button>' } let app = new Vue({ el: '#app', components: { 'button-component': buttonComponent } }) </script>
このプログラムを実行すると、
のようになります。
「ローカルコンポーネント」は、
components: { 'カスタムタグ名': コンポーネント }
のように指定します。
「カスタムタグ」は、
<div id="app"> <button-component></button-component> </div>
のように「Vueインスタンス」をマウントした「HTML要素内」でのみ使うことができます。
内容が複雑になってきましたが、まだ何とか理解できている感じです。
1回学んだだけでは「コンポーネント」を利用したプログラムを書ける気がしないため、繰り返しプログラムを書きながら「コンポーネント」の使い方に慣れていきたいと思います。