Vue.jsにはコンポーネント(テンプレート)という機能があります。
通常ブラウザ上に表示するHTMLのコードはhtmlファイルに記述しますが、コンポーネントにすると、Vue.jsにhtmlのコードを記述し、それに名前をつけてhtmlファイルの好きなところで呼び出すことができるようになります。
繰り返し使用する部分や、htmlファイル上に記述すると煩雑になる記述はコンポーネントとして抜き出すと、htmlファイルがスッキリし管理が簡単になります。
ここでは、グローバルコンポーネントとローカルコンポーネントの違いを含めて、コンポーネントの使い方を実例でまとめています。
コンポーネントとは何か?
そもそもコンポーネントという言葉を聞きなれないかもしれません。
コンポーネントとはお問い合わせフォームやQ&Aなど、コードの記述の一部をひとまとまりの要素として切り出したものです。
作成したコンポーネントには独自の名前を設定することができ、HTMLファイル上でその要素を呼び出したい場所に、コンポーネントの名前を記述すると、そのコンポーネントに含まれているコードを呼び出すことができます。
何度も呼び出すなど、使い回す可能性のある要素をコンポーネント化します。
グローバルコンポーネントとローカルコンポーネントの違い
コンポーネントにはアプリケーションの中ならどこでも呼び出せるグローバルコンポーネントと、指定したVueインスタンスの中でのみ呼び出せるローカルコンポーネントがあります。
テンプレート | 作成方法 |
---|---|
グローバル | Vue.componentを使って定義する。 |
ローカル | new Vueの中のcomponentsオブジェクトで定義する。 |
以下でそれぞれを実例でまとめています。
グローバルコンポーネントの作り方
始めに、アプリケーション内のどのVueでも呼び出すことができるグローバルコンポーネントの作成手順についてです。
グローバルコンポーネントの作り方
グローバルコンポーネントの作り方はとてもシンプルです。(ローカルコンポーネントも同じくしプルです)
JavaScriptのファイル(.jsファイル)に以下のように記述します。
Vue.component('コンポーネント名', {
template: 'HTMLのコード',
data():{
return{
}
},
methods:{
},
computed:{
},
})
dataとmethodsやcomputedでは書き方が異なることに注意してください。 () や returnの有無。詳細は以下で実例を交えて解説しています。
HTMLをコンポーネント化する
コンポーネントではdataオブジェクトやmethodsオブジェクトなど、Vue.jsの記述を書くこともできますが、それ以外にも単にHTMLの要素を再利用可能なブロックとして定義することもできます。
jsファイルにコンポーネントを定義する
//コンポーネントの定義
Vue.component('コンポーネント名', {
template: 'HTMLのコード',
})
//Vueインスタンスの定義
var app = new Vue({
el:'#app'
})
(1)命名ルール
コンポーネント名で全て小文字で複数の単語を使う場合はハイフンでつなげる必要があります。大文字は使えません。
判定 | コンポーネント名の例 |
---|---|
OK | hello-vue |
NG | helloVue |
NG | Hello-vue |
(ここでは割愛しますが、Vueには.vueというファイル名の単一ファイルコンポーネントというコンポーネントの定義方法もあります。そこではHelloVueといった大文字表記も使用することができます)
(2)templateプロパティの値
templateプロパティの値は、最上位のタグが必ず1つである必要があります(入れ子構造はOKです)。
最上位にタグを複数並列に記述すると、最初のタグのみしか反映されません。
OKな例
Vue.component('hello-vue', {
template: '<div> <p>「こんにちは!」</p> <p>「2つ目の要素」</p>',
})
この場合、最上位のタグはdivの1つのみです。
NGな例
Vue.component('hello-vue', {
template: '<p>「こんにちは!」</p> <p>「並列の要素」</p> <br> <div>「並列の要素2」</div>',
})
この場合、最上位に、pタグが2つ、brタグ、divタグの4つのタグがあります。コンポーネントを呼び出したときに反映されるのは1つ目の<p>「こんにちは!」</p>
のみです。
以上でVueコンポーネントの作成は完了です。
HTMLファイルでコンポーネントを呼び出す
HTMLファイルで作成したコンポーネントを呼び出すには以下のようにします。
<コンポーネント名></コンポーネント名>
開始タグと終了タグ(<コンポーネント名></コンポーネント名>
)の間に入力した内容は無視されます。
<body>
<div id="app">
<コンポーネント名></コンポーネント名>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
なお、コンポーネントは何度でも呼び出すことができます。
実例
HTMLのみをVueコンポーネント化して、htmlファイルで呼び出す例です。
hello-vueという名前のグローバルコンポーネントを作成します。
Vue.component('hello-vue', {
template: '<p>「こんにちは!」</p>',
})
var app = new Vue({
el:'#app'
})
htmlファイルの中で、hello-vueを呼び出します。
<body>
<div id="app">
<p>以下でVueコンポーネントを呼び出しています</p>
<hello-vue></hello-vue>
<p>呼び出しは以上です。</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
作成したVueコンポーネントが正しく呼び出されていることが確認できます。

何度も呼び出す例
作成したテンプレートは何度も呼び出すことができます。
上記の例で、HTMLファイルの中で複数回Vueコンポーネントを呼び出してみます。
<body>
<div id="app">
<p>以下でVueコンポーネントを呼び出しています</p>
<hello-vue></hello-vue>
<hello-vue></hello-vue>
<p>呼び出しを以下でも行います。</p>
<hello-vue></hello-vue>
<hello-vue></hello-vue>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
記述した場所でVueコンポーネントが呼び出されていることがわかります。

templateプロパティの値を改行する方法
templateの値をシングルクオーテーションやダブルクォーテーションで指定する場合、改行が使えないため、タグを1行で記載しなければいけません。コードリーディングが非常に見にくくなってしまいます。
templateプロパティの値で改行を使いたい場合は「`(バッククオート)」で囲みます。
バッククオートはshift + @で記述できます。
バッククオートと使うと次のような記述が可能になります。
Vue.component('hello-vue', {
template: `
<dl>
<dt>AAA</dt>
<dt>BBB</dt>
<hr>
<dt>111</dt>
<dt>222</dt>
</dl>`,
})
var app = new Vue({
el:'#app'
})
templateプロパティの値は、最上位のタグが必ず1つである必要があります(入れ子構造はOKです)。最上位にタグを複数並列に記述すると、最初のタグのみしか反映されません。
OKな例
Vue.component('hello-vue', {
template: '<div> <p>「こんにちは!」</p> <p>「2つ目の要素」</p>',
})
この場合、最上位のタグはdivの1つのみです。
NGな例
Vue.component('hello-vue', {
template: '<p>「こんにちは!」</p> <p>「並列の要素」</p> <br> <div>「並列の要素2」</div>',
})
この場合、最上位に、pタグが2つ、brタグ、divタグの4つのタグがあります。コンポーネントを呼び出したときに反映されるのは1つ目の<p>「こんにちは!」</p>
のみです。
htmlファイルの中で、上記のテンプレートを呼び出します。
<body>
<div id="app">
<p>以下でVueコンポーネントを呼び出しています</p>
<hello-vue></hello-vue>
<p>呼び出しは以上です。</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
改行ありのコードもコンポーネントとして呼び出せます。

複数回呼び出す
もちろん、何度も呼び出すことができます。
<body>
<div id="app">
<p>以下でVueコンポーネントを呼び出しています</p>
<hello-vue></hello-vue>
<p>以下でも呼び出します。</p>
<hello-vue></hello-vue>
<p>3回目の呼び出し</p>
<hello-vue></hello-vue>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>

コンポーネントの中でdataオブジェクトを使う方法
通常のVue.jsと同様に、コンポーネントの中でdataオブジェクトを使うこともできます。
dataオブジェクトを使えばVue側に作成したデータをテンプレートで呼び出すことができます。
基本的な書き方
コンポーネント内で、dataオブジェクトを使う書き方は次のようになります。
Vue.component('コンポーネント名', {
template: 'htmlのコード',
data(){
return {
プロパティ名1: 値1,
プロパティ名2: 値2
}
}
})
通常のVueインスタンスとは異なり、dataが関数の形になり、returnで返していることに注意してください。data(){ return{ } }
なお、上記は以下の記述の省略形です。
Vue.component('コンポーネント名', {
template: 'htmlのコード',
data: function(){
return {
プロパティ名1: 値1,
プロパティ名2: 値2
}
}
})
functionを記述せずに、省略形で書くのが一般的です。
実例
dataオブジェクトを持ったコンポーネントを使って、templateオブジェクトの中でプロパティを呼び出します。
コンポーネント内で、dataオブジェクトを使う書き方は次のようになります。
messageとhelloというプロパティを作成し、それをtemplateの中で呼び出しています。コンポーネント名は「data-vue」としています。
Vue.component('data-vue', {
template: '<p>{{hello}} {{message}}</p>',
data(){
return {
message: "初期値のメッセージです。",
hello: "「こんにちは!」",
}
}
})
var app = new Vue({
el:'#app'
})
<body>
<div id="app">
<div>
<p>■dataを使ったコンポーネント</p>
<data-vue></data-vue>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
dataに記述したプロパティの値がコンポーネントの中で呼び出され、ブラウザ上に正しく表示されます。

コンポーネントの中でmethodsを使う方法
Vue.jsではdataオブジェクト以外にも、methods, watch, computedなど様々な便利オブジェクトが使えます。
これらはもちろんコンポーネントの中でも使えます。注意点はdataと違ってreturnは不要ということです。
data以外は基本的に同じ書き方をするので、ここでは代表としてmethodsを使った記述を紹介します。
書き方
template, dataと並列にmethodsを記述します。
methods:{ メソッド名(){ 処理 } }
Vue.component('コンポーネント名', {
template: 'htmlのコード',
data(){
return {
プロパティ名1: 値1,
プロパティ名2: 値2
}
},
methods:{
メソッド名(){
処理
}
}
})
実例
methodsを使った実例として、要素をクリックするとdataにセットした2つのプロパティをつなげて、画面上に表示するプログラムを作ります。
Vue.component('methods-vue', {
template: '<p @click="sayHi">挨拶: {{ output }}</p>',
data(){
return {
name: "AAAさん",
hello: "「こんにちは!」",
output: ""
}
},
methods:{
sayHi(){
this.output = this.name + this.hello
}
}
})
var app = new Vue({
el:'#app'
})
template: '<p @click="sayHi">挨拶: {{ output }}</p>',
HTML上で呼び出すコンポーネントは上記の部分になります。
pタグの要素をクリックするとクリックイベントが発動して、指定したメソッド sayHiを実行します。
sayHi(){
this.output = this.name + this.hello
}
sayHiはプロパティにセットされているnameとhelloの値をつなげて、プロパティoutputにセットします。
結果として、pタグ内で呼び出している {{ output }} が更新され、文字列が画面に表示されます。
@clickなどのイベント処理の詳細については、下記をご参考ください。
htmlファイルの中で、上記のコンポーネントを呼び出します。
<body>
<div id="app">
<div>
<p>■methodsを使ったコンポーネント</p>
<methods-vue></methods-vue>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示

↓ 「挨拶:」をクリック

メソッドが実行され、文字列が表示されました。
グローバルコンポーネントを複数作成する方法
コンポーネント名を変えれば、コンポーネントを複数作成することもできます。
基本的な書き方
//コンポーネントの定義
Vue.component('コンポーネント名1', {
template: 'HTMLのコード',
})
Vue.component('コンポーネント名2', {
template: 'HTMLのコード',
})
//Vueインスタンスの定義
var app = new Vue({
el:'#app'
})
実例
「hello-vue」と「dl-vue」という2つのコンポーネントを作成します。
Vue.component('hello-vue', {
template: '<p>「こんにちは!」</p>',
})
Vue.component('dl-vue', {
template: `
<dl>
<dt>「AAA」</dt>
<dt>「BBB」</dt>
</dl>`,
})
var app = new Vue({
el:'#app'
})
htmlファイルの中で、上記2つのコンポーネントをそれぞれ呼び出します。
<body>
<div id="app">
<div>
<p>複数のコンポーネントを呼び出す</p>
<hello-vue></hello-vue>
<dl-vue></dl-vue>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
ブラウザにそれぞれのコンポーネントの内容が表示されていることがわかります。

ローカルコンポーネントの作り方
どのVueインスタンスでも呼び出せるグローバルコンポーネントと違い、特定のVueインスタンスの中でした呼び出せないローカルコンポーネントを作成することもできます。
ローカルコンポーネントを使うメリットは、コンポーネントの中で定義したdataやmethodsなどがその指定したVueインスタンスの中だけで有効になることです(グローバルに影響しない)
作り方
ローカルコンポーネントはVueインスタンスの中にcomponentsオブジェクトを作成し、その中で定義します。
var app = new Vue({
el:'#app',
components: {
'コンポーネント名': {
template: 'htmlタグ',
data(){
return {}
},
methods:{},
computeds:{}
}
}
})
componentsの直下にコンポーネント名を記載し、その中にtemplateやdata, methods, computedなどを記述します。
実例
Vueインスタンスの中にlocal-helloというコンポーネントを作成し、それをhtmlファイルの中で読み込みます。
var app = new Vue({
el:'#app',
components: {
'local-hello': {
template: '<p>{{ name }}さん。こんにちは!</p>',
data(){
return {
name: "AAA"
}
}
}
}
})
htmlファイルの中で、上記のコンポーネントを呼び出します。
<body>
<div id="app">
<p>ローカルコンポーネントの呼び出し</p>
<local-hello></local-hello>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示

ローカルコンポーネントをVueインスタンスの外に記述する方法
ローカルコンポーネントをVueインスタンスの中に作成すると、コードが長く煩雑になり読みにくくなります。
このため、コンポーネントの中身は外に変数や別ファイルとして切り出し、インスタンスの中でその変数を読み込むのが一般的です。
書き方
変数として定義する場合は以下のようになります。
var 変数名 = {
template: 'htmlタグ'
data(){
return {}
},
methods:{},
computeds:{}
}
var app = new Vue({
el:'#app',
components: {
'コンポーネント名': 変数名
}
})
実例
localCompという変数を定義し、その中にVueテンプレートの内容を記述します。それをVueインスタンスのcomponentsの値として読み込みます。
components: {
'local-hello': localComp
}
jsファイルのコード全体は以下のようになります。
var localComp = {
template: '<p>{{ name }}さん。こんにちは!</p>',
data(){
return {
name: "AAA"
}
}
}
var app = new Vue({
el:'#app',
components: {
'local-hello': localComp
}
})
htmlファイルの中で、上記のコンポーネントを呼び出します。
<body>
<div id="app">
<p>ローカルコンポーネントの呼び出し</p>
<local-hello></local-hello>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示

ローカルコンポーネントを複数作成する方法
グローバルコンポーネントと同じく、ローカルコンポーネントも複数作成することができます。
Vueインスタンスのcomponentsの中で複数のコンポーネントを定義します。
書き方
components: {
'コンポーネント名1': コンポーネント1の中身,
'コンポーネント名2': コンポーネント2の中身,
'コンポーネント名3': コンポーネント3の中身,
,,,,
}
実例
localCompとengHelloという変数を定義し、Vueインスタンスのcomponentsの中でコンポーネントとして読み込みます。
var localComp = {
template: '<p>{{ name }}さん。こんにちは!</p>',
data(){
return {
name: "AAA"
}
}
}
var engHello = {
template: '<p>Hello {{ name }}!</p>',
data(){
return {
name: "BBB"
}
}
}
var app = new Vue({
el:'#app',
components: {
'local-hello': localComp,
'eng-hello': engHello
}
})
それぞれのコンポーネントは独立とみなされるため、dataオブジェクトにnameプロパティを設定していますが、別物として扱われます。
htmlファイルの中で、上記のコンポーネントを呼び出します。
<body>
<div id="app">
<p>ローカルコンポーネントの呼び出し</p>
<local-hello></local-hello>
<eng-hello></eng-hello>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
それぞれのコンポーネントの内容が呼び出されています。{{ neme }} にはそれぞれのプロパティの値が入っています。

グローバルとローカルコンポーネントの併用
最後に、参考としてグローバルとローカルコンポーネントを併用したプログラムを記載しておきます。
ブラウザ上のボタンをクリックすると1づつ加算するコンポーネントです。
localCompとengHelloという変数を定義し、Vueインスタンスのcomponentsの中でコンポーネントとして読み込みます。
//■グローバルコンポーネント
Vue.component('hello-component', {
template: '<p>Hello World</p>',
})
//■dataを使ったコンポーネント
Vue.component('data-vue', {
template: '<p>{{mes1}} {{mes2}}</p>',
data(){
return {
mes1: "AAAさん。",
mes2: "こんにちは",
}
}
})
//■ボタンカウンターコンポーネント
Vue.component('button-counter', {
data() {
return {
count: 0
}
},
template: '<div><span>Please Click: <button v-on:click="count++">{{count}}</button></span></div>'
})
//■ローカルコンポーネント
var localComponent = {
template: '<p>ローカルからこんにちは!</p>'
}
var app = new Vue({
el:'#app',
components: {
'local-component': localComponent
}
})
<body>
<div id="app">
<div>
<p>■グローバルコンポーネント</p>
<hello-component></hello-component>
</div>
<br><hr>
<div>
<p>■dataを使ったコンポーネント</p>
<data-vue></data-vue>
</div>
<br><hr>
<div>
<p>■ローカルコンポーネント</p>
<local-component></local-component>
</div>
<br><hr>
<div>
<p>■ボタンカウンター</p>
<button-counter></button-counter>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
1つのページ上に、グローバルコンポーネントとローカルコンポーネントを同時に表示できます。
