前回までの記事
vue.jsを初めて学ぶ ④ [VueCLI 3.7.0 + Vue.js 2系のインストール]
目次
コンポーネントとは
以前までの記事とは、書き方が異なってくる
いいね数を表示する
従来のVue.js書き方
<div id="app">
</div>
new Vue({
el:'#app',
data: {
number: 12
},
template: '<p>いいね{{number}}</p>'
})
コンポーネントを利用した書き方
<div id="app">
<my-component></my-component>
</div>
Vue.component('my-component', {
data: function(){
return {
number: 12
}
},
template: '<p>いいね{{number}}</p>'
})
new Vue({
el:'#app',
})
-
Vue.componentを作成する。
-
Vue.componentでは、
第1引数=>[コンポーネント名]
第2引数=>[プロパティ]
が入る -
Vue.component内のdataプロパティでは、
関数(returnによる返り値)を用意しないと駄目 -
new Vueインスタンス内のelプロパティでは、
html側の'#app'を指定している -
html側では、
コンポーネント名の第1引数をタグとして用意、
代入される。
なぜ?
コンポーネントでは、
dataプロパティ内の変数を
関数として扱わないと駄目か?
-
オブジェクト形式では、
変数が参照→変数に処理が加わる
全コンポーネントで適用 -
関数の形式では、
変数に処理が加わる
単体のコンポーネントのみに適用
実例 : +1されるボタン(オブジェクトver)
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
//無理やり、オブジェクト形式のdataをreturnにセットしている。
var data = {
number: 12
}
Vue.component('my-component', {
data: function(){
//returnされているけど、中身はオブジェクトのnumberが入っている。
return data
},
template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
methods: {
countUp: function(){
this.number += 1;
}
}
}),
new Vue({
el:'#app',
})
オブジェクト形式のnumber(12)を+1すると、
すべてのコンポーネント内の変数numberに適用
実例 : +1されるボタン(関数ver)
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
Vue.component('my-component', {
data: function(){
return {
number: 12
}
},
template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
methods: {
countUp: function(){
this.number += 1;
}
}
}),
new Vue({
el:'#app',
})
単体のコンポーネントに対して適用されているのが分かる。
ローカル登録 と グローバル登録
グローバル登録とは?
- 全インスタンスが使用できる
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<hr>
</div>
<div id="app2">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<hr>
</div>
Vue.component('my-component', {
data: function(){
return {
number: 12
}
},
template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
methods: {
countUp: function(){
this.number += 1;
}
}
}),
new Vue({
el:'#app',
})
new Vue({
el:'#app2',
})
グローバル登録の結果
インスタンス'div#app' と 'div#app2' どちらも適用
ローカル登録とは?
- 特定のインスタンスのみが使用できる
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<hr>
</div>
<div id="app2">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
<hr>
</div>
var component = {
data: function(){
return {
number: 12
}
},
template: '<p>いいね{{number}}<button v-on:click="countUp">+1</button></p>',
methods: {
countUp: function(){
this.number += 1;
}
}
}
new Vue({
el:'#app',
components: {
'my-component': component
}
})
new Vue({
el:'#app2',
})
-
varで、
変数を用意する。 -
変数に、
グローバル登録していた
コンポーネントの 第2引数 をすべて格納する。 -
ローカル登録したいインスタンスへ、
componentsプロパティ を持たせる。 -
componentsプロパティ は、
オブジェクト形式で
・キーにhtml側で代入するタグ名
・バリューには先程格納した変数名
を指定する
ローカル登録の結果
インスタンス 'div#app' のみに、divタグが適用
コンポーネントの概念
-
Vueプロジェクトでは、
main.js内のimportによって、
・指定の.vueファイル
を読み込んでコンポーネントとして使用している。 -
App.vueファイルでは、
importによって、
・componentsディレクトリ配下の.vueファイル
を読み込んでコンポーネントとして使用している。
[Vue-CLI3.7.0によって、vue createされたディレクトリ構成]
// (1)
import App from './App.vue'
// (2)
new Vue({
render: h => h(App),
}).$mount('#app')
<script>
// (3)
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
// (4)
HelloWorld
}
}
</script>
- ファイルのimport時に、
コンポーネント名がfromで指定される。
各インスタンスで、使用できる
templateタグの注意点
親要素として一つでないと、エラーとなる。
+1をするメソッド追加 エラー パターン
import Vue from 'vue'
import App from './App.vue'
// グローバル登録(1)
import LikeNumber from "./LikeNumber.vue"
Vue.config.productionTip = false
// グローバル登録(1)
Vue.component('LikeNumber', LikeNumber);
new Vue({
render: h => h(App),
}).$mount('#app')
<template>
<LikeNumber></LikeNumber>
</template>
<template>
// 親要素が2つだと、エラーになる!
<p>いいね({{number}})</p>
<button @click="countUp">+1</button>
</template>
<script>
export default {
data() {
return {
number: 6
}
},
methods: {
countUp(){
this.number += 1;
}
}
}
</script>
divタグで括り、親要素を1つに
<template>
<div>
<p>いいね({{number}})</p>
<button @click="countUp">+1</button>
</div>
</template>
これでエラーがなくなる
ケバブとパスカルケース記法
<LikeHeader></LikeHeader>
<like-header></like-header>
プロジェクト内では、どちらかのケース記法で統一しよう。
・HTML要素は、ケバブケース
なので目視でわかりやすくするため
パスカルケースがおすすめ
htmlタグ内では、ケバブケース記法統一がおすすめ!
// キャメルケース
<LikeNumber :totalNumber="number"></LikeNumber>
// ケバブケース
<LikeNumber :total-number="number"></LikeNumber>
htmlでは、大文字を判別できない。
公式でもhtmlタグ内では、ケバブケースを推奨
コンポーネント間のデータ受け渡し
親要素から子要素への、データ受け渡し
各いいね数とトータルいいね数
<template>
<div>
<likeHeader></likeHeader>
<h2>{{ number }}</h2>
<LikeNumber :number="number"></LikeNumber>
<LikeNumber :number="number"></LikeNumber>
</div>
</template>
<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
data() {
return {
number: 10
}
},
components: {
LikeHeader
}
}
</script>
親要素であるApp.vue内の
dataプロパティ
number:10 を受け渡す
propsプロパティを使用する
<template>
<div>
<p>いいね({{ number / 2 }})</p>
</div>
</template>
<script>
export default {
props: ["number"],
}
</script>
子要素であるLikeNumber.vue内にて、
propsプロパティを 配列[ ] で指定する。
number:10が使用できる。
子要素から親要素への、データ受け渡し
+1ボタンを子要素に設置、押すと親要素のトータルいいね数が変更される。
-
$emit が必須!
- カスタムイベントを作成できる。
<template>
<div>
<likeHeader></likeHeader>
<h2>{{ number }}</h2>
<LikeNumber :total-number="number" @my-click="number = $event"></LikeNumber>
<LikeNumber :total-number="number"></LikeNumber>
</div>
</template>
<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
data() {
return {
number: 10
}
},
components: {
LikeHeader
}
}
</script>
<template>
<div>
<p>いいね({{ harfNumber }})</p>
<button @click="incriment">+1</button>
</div>
</template>
<script>
export default {
props: ["totalNumber"],
computed: {
harfNumber() {
return this.totalNumber / 2;
}
},
methods: {
incriment() {
this.$emit("my-click", this.totalNumber +1);
}
}
};
</script>
-
LikeNumber.vueファイル内で、
methodsプロパティで、
totalNumberに+1する関数を作成。
$emitを用いて、
・第1引数にカスタムイベント名を
・第2引数にイベント処理
を書く -
App.vueファイル内で、
v-on:my-click時、
親要素のnumberが$emitで発火した値を$eventで拾い、値を更新する。