部品を再利用するコンポーネント
コンポーネントは、プラモデルで言うと、頭、動体、手、足といったパーツを組み立てて完成させるのと同じような感覚です。
Webページも同じでヘッダー 、ボディ、フッター、サイドバーのパーツで構成されています。
vue.jsでは、このコンポーネント(部品)を独自のタグを作って、使用していきます。
【コンポーネント化のメリット】
・開発やテストがコンポーネント単位で行うことができる ➡︎ 開発が楽!
・処理を部品にしておくことで、使い回すことができる ➡︎ 開発が楽!!
とにかく、機能を部品化、共通化することで、開発が楽になるのです。
では、具体的にコンポーネントの作り方をみていきましょう!
コンポーネント作成 その1
これから、<alert-component></alert-component>
という独自のタグを作成して、HTMLで使えるようにしてみたいと思います。
Vue.component
と言うメソッドを使用します。
main.jsに次のように記述してください。
Vue.component('alert-component', {
template: ``
});
まず、
Vue.component
の()
の中にalert-component
と書きました。
これで、HTMLの中で<alert-component></alert-component>
と言う名前のタグが使えるようになります。
続いて、 template:
の部分で バッククォートで囲むと、HTMLの記述が可能になります。
コンポーネントは、new Vue
される前に定義する必要があることに注意してください。
Vue.component('alert-component', {
template: `
<div class="alert">
アラート!
</div>
`
});
var app = new Vue({
el: '#app'
});
ここまで書いたら、HTMLに <alert-component></alert-component>
を書いてみましょう。
<body>
<div id="app">
<alert-component></alert-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="js/main.js"></script>
</body>
独自に作成した、タグを書いただけで「アラート!」と言う文字を表示されました。
コンポーネントの基本的な作り方がわかったので、いくつか機能を追加してみます。
せっかくなので、練習も兼ねて「クリックされたら、アラートを発生させる」という機能をvue.jsで作ってみましょう。
クリックされたら、なので v-on
を使います。
<styles.css>
.alert {
background-color: pink;
border: 1px solid red
}
<main.js>
Vue.component('alert-component', {
template: `
<div class="alert" v-on:click="caution">
アラート!
</div>
`,
methods: {
caution: function() {
alert('クリックされました');
}
}
});
var app = new Vue({
el: '#app'
});
v-on:click
で"caution"
を指定したので、"caution"
の処理の中身をfunctionで記述しています。
以上で、 <alert-component></alert-component>
と言う独自のコンポーネントの出来上がりです。
これで今後は <alert-component></alert-component>
を増やしていくだけで、今作成した機能を簡単に使用することができるようになりました。
コンポーネント作成 その2
コンポーネントには グローバル
と ローカル
があります。
実は先ほど使った Vue.component
は ‘グローバル’ への登録になります。
グローバル
と ローカル
の違いはこの後確認するので、まずは ローカル
の登録について見ておきます。
Vueインスタンスにcomponentsプロパティを追加します
var app = new Vue({
el: '#app',
data: {
},
//ここにコンポーネントを書いていく
components: {
'hello-world': {
template: '<h1>Hello World</h1>'
}
}
});
components
プロパティを追加して、その中にコンポーネントの中身を書いていきます。
HTMLで<hello-world></hello-world>
という名前のタグが使えるようになります。
グローバルとローカルの違い
グローバルで登録したコンポーネント → 別のVueインスタンスで使用可能
ローカルで登録したコンポーネント → 別のVueインスタンスで使用できない
具体的に確認してみます。
//グローバルの作り方
Vue.component('hello-global', {
template: `<h1>グローバルのコンポーネント</h1>`
})
var app = new Vue({
el:'#app',
data: {
}
})
//ローカルの作り方
var app2 = new Vue({
el: '#app2',
components: {
'hello-local': {
template: `<h1>ローカルのコンポーネント</h1>`
}
}
})
<body>
<div id="app">
<hello-global></hello-global>
<hello-local></hello-local>
</div>
<div id="app2">
<hello-global></hello-global>
<hello-local></hello-local>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="js/main.js"></script>
</body>
緑色で囲われた部分が、ローカルのコンポーネントです。
app2
の中で作ったコンポーネントなので、別の箇所では使用できないことが分かります。
親子関係を意識したコンポーネント
コンポーネントには 親コンポーネント
と 子コンポーネント
があり、
親 → 子
と 子 → 親
の2パターンでデータの受け渡しが行えます。
受け渡し方は両者で異なるので、その方法を見ていきましょう。
この後見ていく中で 「どっちが親でどっちが子なんだろう…」 と、なってしまった時は次のように考えてください。
親=コンポーネントを利用する側
子=コンポーネントを利用される側
(厳密には、「HTMLが親」というよりは、「Vueインスタンスが親」というのを頭の片隅に置いておいてください)
親 → 子(props)
親 → 子
のデータの受け渡しには props
を使用します。
「親コンポーネントが子コンポーネントにお小遣いをあげている」 というのをイメージしてください。
<子>
Vue.component('pocket-money', {
template: `<h1>{{ money }}円もらいました</h1>`,
props: ['money']
})
var app = new Vue({
el: '#app',
data: {
}
})
<親>
<body>
<div id="app">
<pocket-money money="1,000"></pocket-money>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="js/main.js"></script>
</body>
解説
親の方で、money
という属性(1,000)を子に渡しています。
子の方は、props
でその属性(1,000)を受け取っています。
子 → 親($emit)
子から親のデータの受け渡しはちょっと複雑な内容なのでこのカリキュラムでは、
どのようにデータを渡しているのかという流れだけ確認出来ればOKです。
これから、
「子コンポーネントからイベントを発火させて、親要素の方で結果を検出する」
といったことを行います。
具体的には、「回数を数えるボタン(子コンポーネント)を用意して、押された回数を画面(親コンポーネント)に表示する」という状況を再現してみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>My Vue App</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div id="app">
<p>カウント数: {{ total }}</p>
<count-component v-on:increment="incrementTotal"></count-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="js/main.js"></script>
</body>
</html>
Vue.component('count-component', {
template: `<button v-on:click="countBtn">+1</button>`,
methods: {
countBtn: function() {
this.$emit('increment')
}
}
})
var app = new Vue({
el:'#app',
data: {
total: 0
},
methods: {
incrementTotal: function() {
this.total++;
}
}
})
まとめ
今回は、以下の3点について見てきました。
・グローバルとローカルの作成
・親 → 子(props)
・子 → 親($emit)