初めてのVue③コンポーネントの使用
コードが複雑になるにつれ、どこに何を書いたかわからなくなる場合があります。そんな時にはコンポーネントという機能が大変便利です。コンポーネントを使うことで部品を組み立てるようにコードを使うことができるようになります。Vueを扱う上で必須の知識となるので、ぜひ理解しておきましょう。
- コンポーネントって何?
- Vueについて学びたい
- templateを使いたい
コンポーネントの使い方
まずはコードです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Document</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app4">
//ポイント①:id="app4"の中で使えるapp-buttonを使います。
<app-button>submit</app-button>
</div>
<script>
let app4 = {
//ポイント②:componentによってapp-buttonでbuttonタグが使えるように定義します。
components: {
'app-button': {
template: `
<button :disabled="processing">
<slot/>
</button>
`,
//ポイント③:dataによって変数を定義できます。
data(){
return{
processing: true
};
}
},
}
};
Vue.createApp(app4).mount('#app4');
</script>
</body>
</html>
ブラウザでは↓のような感じです。
ポイントはコードの中に書いたとおりです。
書き方は覚えるしかないです。テンプレをコピペして修正するのが早いです。
コンポーネントの整理
コンポーネントが1つの時は気にならないのですが、複数になったときには各コンポーネントでファイルを作成した方がすっきりします。
そのために、まずはフォルダとファイルを作っていきます。
index.htmlと同じ階層にcomponentフォルダを作成してApp.jsとAppButton.jsファイルを作成しました。
ファイルの中身は下記の通りです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Document</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app4">
<app-button>submit</app-button>
</div>
<script type="module">
//ポイント:App4をインポートしてマウントしています
import App4 from "./js/components/App.js";
Vue.createApp(App4).mount('#app4');
</script>
</body>
</html>
import AppButton from "./AppButton.js";
//ポイント:インポートしたAppButtonをapp-buttonとして使えるようにエクスポートしてます。
export default {
components: {
'app-button': AppButton
}
};
//ポイント:AppButtonの具体的な中身はここで書きます。
export default {
template: `
<button :disabled="processing">
<slot/>
</button>
`,
data(){
return{
processing: true
};
}
}
このように分けることでコンポーネントが増えてもわかりやすくなります。
全てのコンポーネントを一度App.jsでまとめてindex.htmlに送るとするとコンポーネント一覧があるのでわかりやすいです。
密かなポイント
scriptタグにtype,moduleを設定しているのもポイントです。
モジュールタイプにしていないと下記のエラーが発生します。
Uncaught SyntaxError: Cannot use import statement outside a module (at (index):118:5)
これで綺麗になりました。
Propsについて
ついでにPropsについても学んでいきましょう。
コンポーネントのように複数のファイルにまたがってデータを渡すときに役立ちます。
まずはコードです。
<div id="app4">
<app-button type="primary">submit</app-button> //タイプを追加
</div>
export default {
template: `
<button :disabled="processing">
<slot/>
</button>
`,
//ここを追加
props:{
type: String
}
data(){
return{
processing: true
};
}
}
ブラウザのDevtoolで確認します。
typeにprimaryが設定されています。
primaryが文字列のためpropsではstringを設定しました。
次にデフォルトでprimaryになるように設定します。
<div id="app4">
<app-button>submit</app-button>
</div>
props:{
type: {
type: String,
default: 'primary'
}
},
ブラウザで確認します。
うまくいきました。
AppButton.jsのtypeがややこしいですが、最初のtypeがpropsの名前、後のtypeがpropsのタイプとなります。
classの追加
では、この機能を活かしてclassを追加してみます。
export default {
template: `
<button
ここを追加
:class="{
'border rounded px-5 py-2': true,
'bg-blue-200': type === 'primary',
'bg-green-200': type === 'secondary',
'bg-red-200': type === 'third',
}"
:disabled="processing"
>
<slot/>
</button>
`,
props:{
type: {
type: String,
default: 'primary'
}
},
data(){
return{
processing: true
};
}
}
CSSが反映されるようにindex.htmlに下記を追記します。
<script src="https://cdn.tailwindcss.com"></script>
ブラウザで確認します。
うまくいっています。
classに記入したCSSはboolean型となります。typeにprimaryを設定しているので青く表示されます。
ついでにdataの記述もpropsの中に入れてみます。
props:{
type: {
type: String,
default: 'primary'
}
processing:{
type: Boolean,
default: true
}
},
// data(){
// return{
// processing: true
// };
// }
dataにアクセスしてもpropsにアクセスしても結果は同じになります。
今回はデータの受け渡しがなかったですが、親から子にデータを渡す時にはpropsをv-bindして渡すようになります。
いづれ出てくるのでお楽しみに!