Vue.js を1から学んでみた。にて書いてきましたが、
長くなり編集しにくくなってきたので、分割しました(こんなやりかたしないのかな?知りたい。)
8-1. Vue CLIとは
Vueのフレームワーク。
簡単に利用でき、サーバーを立ち上げることができる。
$ vue create vue-cli-sample
Vue CLI v4.4.6
? Please pick a preset: default (babel, eslint)
Vue CLI v4.4.6
✨ Creating project in /Users/shinri/development/study/vuejs/vue-cli-sample.
🗃 Initializing git repository...
⚙️ Installing CLI plugins. This might take a while...
・・・省略
$ cd vue-cli-sample/
$ npm run serve
> vue-cli-sample@0.1.0 serve /Users/shinri/development/study/vuejs/vue-cli-sample
> vue-cli-service serve
INFO Starting development server...
98% after emitting CopyPlugin
DONE Compiled successfully in 2287ms 13:24:23
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.100.16:8080/
Note that the development build is not optimized.
To create a production build, run npm run build.
http://localhost:8080/ にアクセスするとVueの画面が表示される。
8-2. Vue CLI構成
初期ディレクトリ概要
- node_modules
- nodeでインストールされた様々なモジュール群
- 何か便利なライブラリを見つけたらnpmでインストールするが、ここに入る
- public
- 静的なファイルを置いておく。webpackの対象にならない。
- index.html しか初期は入っていない(favicon除く)。
- あんまり追加しない。
- src
- vueファイルを書いてアプリを作る(雑)
- webpackの対象となる
初期ファイル概要
- .gitIgnore
- gitにpushしないファイル/ディレクトリの指定
- babel.config.js
- ES5にする時の指定。
- 初期設定のままで基本はOK。複雑なものを作る場合は別。
- package.json
- 使用するライブラリのバージョンを指定する
- scriptsでは、コマンドのオプションを指定する。
$npm run serve
は、"serve": "vue-cli-service serve"
のように定義されている
- package-lock.json
- git等で複数人で開発する場合、こちらを使ってインストール・・・という曖昧な認識。
- 「package-lock.jsonについて知りたくても聞けなかったこと」を参考にさせていただくのがベスト。
srcディレクトリ詳細
assetsディレクトリ
ロゴファイルなど、リソースを入れる。
main.js
render関数で、App.vueオブジェクトを指定しているのみ。
#appにマウントしているが、これはpublic/index.htmlに指定されている。
つまり、App.vueオブジェクトをindex.htmlに表示させていることになる。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!-- ↓ここに#appが指定されている -->
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
単一ファイルコンポーネントと呼ばれる。
画面に表示する内容を、このコンポーネントで実装する。
なお、.vueファイルはVue CLIで使われることで、webpackにて単一コンポーネントとして扱われる。
import App from './App.vue'
のように定義すると、.vueファイル内で単一コンポーネントとして使用できる。
以下の初期作成の例では、HellowWorld.vueコンポーネントを作成し、
それをApp.Vueでタグで使うことで画面を表示させている。
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
本番用ビルド
$ npm run build
を実行することで、src,publicの内容が最適化ビルドされ、distディレクトリが作成される。
これをそのまんまリリースできる。
8-3. Vueコンポーネントの基本
Vueコンポーネント(.vueファイル)は、以下で構成される。
- template
- DOMとして展開される内容を記述する箇所
- scriptにrender関数があれば、不要。
- 注意点:ルート要素は必ず1つであること。エラーになる
- script
- JavaScriptで記載する箇所
- 特に必要なければ、不要。
- style
- CSSを記載する箇所
- CSSが不要であれば、不要。
templateとscriptだけを書いて簡単なvueにて実行してみる
<template>
<p>こんにちは{{name}}さん</p>
</template>
<script>
export default {
data: function() {
return {
name: "太郎"
}
}
}
</script>
<!-- styleは消しました -->
http://localhost:8080/ にアクセスするとVueの画面が表示される。
補足:ルート要素は1つ
以下のように、template
配下にルート要素を2つ以上持つと、コンパイルエラーとなる。
<template>
<p>こんにちは{{name}}さん</p>
<p>こんにちは{{name}}さん</p>
</template>
error in ./src/FirstName.vue?vue&type=template&id=50ec6832&
Module Error (from ./node_modules/vue-loader/lib/loaders/templateLoader.js):
(Emitted value instead of an instance of Error)
Errors compiling template:
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
1 |
2 | <p>こんにちは{{name}}さん</p>
|
3 | <p>こんにちは{{name}}さん</p>
| ^^^^^^^^^^^^^^^^^^^^^^
4 |
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
一つにしなさいと怒られます。ただ、シンプルに機能を分けるサポートをしてくれるという意味では助かることかと。
8-4. Vueコンポーネントのグローバル登録
どこの.vueでも単一コンポーネントを使えるように、グローバル登録を行う。
グローバル登録はmain.js
に対して行う。
以下のように、FirstName.vue
を新規作成し、グローバル登録した後、そのコンポーネントを使用する。
<template>
<p>こんにちは{{name}}さん</p>
</template>
<script>
export default {
data: function() {
return {
name: "次郎"
}
}
}
</script>
<template>
<!-- グローバル登録したコンポーネントを使用 -->
<FirstName></FirstName>
</template>
import Vue from 'vue'
import App from './App.vue'
// コンポーネント追加
import FirstName from './FirstName.vue'
Vue.config.productionTip = false
// グローバル登録
Vue.component("FirstName", FirstName);
new Vue({
render: h => h(App),
}).$mount('#app')
8-5. Vueコンポーネントのローカル登録
グローバル登録の次にローカル登録について。
単一コンポーネントのローカル登録と同じく、Js内(今回で言うと、<script>
内)でimportし、vueインスタンスのcompnent
に登録する。
以下のように、LastName.vue
を新規作成し、ローカル登録した後、そのコンポーネントを使用する。
※main.js
とFirstName.vue
は変わらないので割愛。
<template>
<div>
<p>私は{{name}}です</p>
</div>
</template>
<script>
export default {
data: function() {
return {
name: "山田"
}
}
}
</script>
<template>
<!-- ルートは一つ -->
<div>
<!-- グローバル登録したコンポーネントを使用 -->
<FirstName></FirstName>
<!-- ローカル登録したコンポーネントを使用 -->
<LastName></LastName>
</div>
</template>
<script>
import LastName from "./LastName.vue";
export default {
components: {
LastName: LastName
}
}
</script>
8-6. VueコンポーネントのCSS
<style>
タグにCSSを書けば良いが、必ずscopedをつける。
そうすることで、同じvue内のtemplateにのみ適用させることができる。
<template>
<div>
<p>こんにちは{{name}}さん</p>
</div>
</template>
<script>
export default {
data: function() {
return {
name: "次郎"
}
}
}
</script>
<!-- `scoped`をつける -->
<style scoped>
div {
border: 1px blue solid;
}
</style>
scopedを付けないと、全div
に反映されてしまう
<!-- `scoped`をつけない -->
<style>
div {
border: 1px blue solid;
}
</style>
8-7. コンポーネント間のデータの受け渡し(親→子:props)
基本:プリミティブ/配列/オブジェクト
親→子の場合、props
を使います。
例として、App.vue
から数値と文字列を受け渡すやり方を載せます。
注意:propsは変更値不可なので、子画面で利用する場合は変数に詰め替えてから使う。
<template>
<div>
<p>こんにちは{{name}}さん</p>
<button @click="changeMethod">押した分だけ年齢増えます</button>
<p>年齢:{{age}}</p>
<p>性別:{{gender}}</p>
</div>
</template>
<script>
export default {
// 親→子の受け渡しに`props`を使う。
// 子では受け口として定義するイメージ。
// 書き方は配列かオブジェクトで可能。
// ただ、詳しく書きたいのであれば、オブジェクト型とする。
props: {
// 変数名:キャメルケース
yourAge: {
type: Number, // 型
required: true // 必須かどうか
},
gender: {
type: String,
required: true
}
},
data: function() {
return {
name: "次郎",
// propsのデータは変更不可が推奨されているため、
// このようにdataに設定する
age: this.yourAge
}
},
methods:{
changeMethod: function() {
// propsの値は変更させない
this.age += 1
}
},
}
</script>
<style scoped>
div {
border: 1px blue solid;
}
</style>
<template>
<div>
<!-- ケバブケースでOK -->
<!-- propsの値を設定する。v-bindも勿論OK! -->
<FirstName :your-age="defaultAge" gender="男性"></FirstName>
<LastName></LastName>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15
}
},
components: {
LastName: LastName
}
}
</script>
応用:slot
htmlをそのまんま渡す場合、
v-htmlタグを使って頑張ればいけそうだけど、めんどくさい笑
その代わりにVueコンポーネント内に(DOM要素のように)htmlを書けるようにすることができる機能がある。
そのためにslot
タグとv-slot
ディレクティブを使う (ジャグラー打ちてー)。
1つslotの例
<template>
<div>
<!-- slotタグを指定 -->
<slot></slot>
</div>
</template>
<template>
<div>
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<!-- 要素にHTMLを指定 -->
<LastName>
<p>私は山田です</p>
<p>職業はSEです</p>
</LastName>
<p>思っていた年齢{{defaultAge}}歳でしたが、{{emitData}}歳違っていたようでした。すみません。</p>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
emitData: 0
}
},
components: {
LastName: LastName
}
}
</script>
複数のslotの例
結論から言うと、template
タグと、v-slot
ディレクティブを使う。
<template>
<div>
<!-- slotタグのnameにテンプレート名を指定 -->
<slot name="name"></slot>
<hr>
<!-- slotタグのnameにテンプレート名を指定 -->
<slot name="job"></slot>
</div>
</template>
<template>
<div>
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<LastName>
<!-- v-slotでテンプレート名を指定 -->
<template v-slot:name>
<p>私は山田です</p>
</template>
<!-- v-slotでテンプレート名を指定 -->
<template v-slot:job>
<p>職業はSEです</p>
</template>
</LastName>
<p>思っていた年齢{{defaultAge}}歳でしたが、{{emitData}}歳違っていたようでした。すみません。</p>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
emitData: 0
}
},
components: {
LastName: LastName
}
}
</script>
デフォルトslotの例
template
がついていないものは、Vue.jsが<template v-slot:defalut>
を勝手に作成しまとめる。
あくまでも、slot
を使う場合はtemplate
が必要ということ。
<template>
<div>
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<LastName>
<!-- templateがついていないのは、デフォルトスロットとしてまとめられる1 -->
<p>デフォルトスロット用1</p>
<!-- v-slotでテンプレート名を指定 -->
<template v-slot:name>
<p>私は山田です</p>
</template>
<!-- v-slotでテンプレート名を指定 -->
<template v-slot:job>
<p>職業はSEです</p>
</template>
<!-- templateがついていないのは、デフォルトスロットとしてまとめられる2 -->
<p>デフォルトスロット用2</p>
</LastName>
</div>
</template>
<template>
<div>
<!-- デフォルトスロット表示用 -->
<slot></slot>
<hr>
<!-- slotタグのnameにテンプレート名を指定 -->
<slot name="name"></slot>
<hr>
<!-- slotタグのnameにテンプレート名を指定 -->
<slot name="job"></slot>
</div>
</template>
スロットプロパティ
スロットプロパティを使えば、子のdataを使うことができる。
- 親の指定
-
<template v-slot:name="slotProps">
←"slotProps"
がスロットプロパティ(の名称)。 - 好きな命名でOK。
-
- 子の指定:
<slot name="title" :name="name">
←v-bindを使って、スロットプロパティを指定する。 - 子はVueインスタンスのフィールドを使用して、親のスロットプロパティが受け取るイメージ。
<template>
<div>
<!-- デフォルトスロット表示用 -->
<slot></slot>
<hr>
<!-- v-bindでスロットプロパティを定義 -->
<slot name="name" :sei="sei" :mei="mei"></slot>
<hr>
<!-- slotタグのnameにテンプレート名を指定 -->
<slot name="job" :syokugyou="syokugyou"></slot>
</div>
</template>
<script>
export default {
props: {
job: {
type: String,
required: false
}
},
data: function() {
return {
sei: "山田",
mei: "太郎",
syokugyou: this.job
}
}
}
</script>
<template>
<div>
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<LastName :job="job">
<!-- スロットプロパティ「slotProps」を定義 -->
<template v-slot:name="slotProps">
<!-- このタグでのみ「slotProps」使用できる -->
<p>私は{{slotProps.sei}}{{slotProps.mei}}です</p>
</template>
<!-- スロットプロパティ「hoge」を定義 -->
<template v-slot:job="hoge">
<!-- このタグでのみ「hoge」を 使用できる -->
<p>職業は{{hoge.syokugyou}}です</p>
</template>
</LastName>
<p>思っていた年齢{{defaultAge}}歳でしたが、{{emitData}}歳違っていたようでした。すみません。</p>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
emitData: 0,
job: "家庭教師"
}
},
components: {
LastName: LastName
}
}
</script>
スロットプロパティ(デフォルトスロットのみ)
デフォルトスロットのみの場合、templateタグが不要(Vue.jsが勝手にtemplateタグを付与してくれる)。
その時のスロットプロパティは、単一コンポーネントに定義する。
<template>
<div>
<!-- デフォルトスロット表示用 -->
<slot :sei="sei" :mei="mei" :syokugyou="syokugyou"></slot>
</div>
</template>
<script>
export default {
props: {
job: {
type: String,
required: false
}
},
data: function() {
return {
sei: "山田",
mei: "太郎",
syokugyou: this.job
}
}
}
</script>
<template>
<div>
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<!-- デフォルトスロットのときのスロットプロパティの命名 -->
<LastName :job="job" v-slot:default="slotProps">
<!-- <LastName :job="job" v-slot="slotProps"> のようにdefalutは省略可-->
<!-- templateがなくデフォルトスロットのみ -->
<p>私は{{slotProps.sei}}:{{slotProps.mei}}です</p>
<p>職業は{{slotProps.syokugyou}}です</p>
</LastName>
<p>思っていた年齢{{defaultAge}}歳でしたが、{{emitData}}歳違っていたようでした。すみません。</p>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
emitData: 0,
job: "広告業界"
}
},
components: {
LastName: LastName
}
}
</script>
v-slotの省略記法
#
に置き換えることができる
<template v-slot:job="hoge">
を
<template #job="hoge">
このように省略して書ける。
ただし、defaultスロットについては省略はNG。
8-8. コンポーネント間のデータの受け渡し(子→親:$emit)
子→親の場合、$emit
を使います。
元々、$emit
は、カスタムイベントを作る時に使用される。
任意のタイミングで$emit
を実行することで、親のVueコンポーネント(今回はApp.vue
)でイベントを発火させる。
その発火する時に、データを付け加えて戻すような仕組み。
重要:子は親のデータを変更することはできない。あくまでも子からデータを返している。
なお、カスタムイベントはJavaScript内では使われない。
よって(htmlは大文字小文字を区別しないので)、ケバブケースで命名するのが良い。
<template>
<div>
<p>こんにちは{{name}}さん</p>
<button @click="changeMethod">押した分だけ年齢増えます</button>
<p>年齢:{{age}}</p>
<p>性別:{{gender}}</p>
</div>
</template>
<script>
export default {
props: {
yourAge: {
type: Number,
required: true
},
gender: {
type: String,
required: true
}
},
data: function() {
return {
name: "次郎",
age: this.yourAge
}
},
methods:{
changeMethod: function() {
this.age += 1
// 子→親への値受け渡し。
// $emitで値を返す。正確いうと、親のイベントを発火させて、引数で渡す。
// 第1引数:イベント名(ケバブケースで指定する)、第2引数:イベントで渡す値(任意)
// 元々 $emit はカスタムイベントを作る時に使用。
this.$emit("my-click", this.age - this.yourAge)
}
},
}
</script>
<style scoped>
div {
border: 1px blue solid;
}
</style>
<template>
<div>
<!-- v-onディレクティブでイベントを受け取る -->
<FirstName :your-age="defaultAge" gender="男性" @my-click="emitData = $event"></FirstName>
<LastName></LastName>
<p>思っていた年齢{{defaultAge}}歳でしたが、{{emitData}}歳違っていたようでした。すみません。</p>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
emitData: 0
}
},
components: {
LastName: LastName
}
}
</script>
8-8. コンポーネントの動的切り替え
同じ場所に表示するコンポーネントを切り替える時には、component
タグを使う。
以下、新たに ParentコンポーネントとChildコンポーネントを定義し、切り替える。
<template>
<div>
<p>親の山田一郎です</p>
</div>
</template>
<template>
<div>
<p>子供の山田一太郎です</p>
</div>
</template>
<template>
<div>
<!-- クリックでコンポーネントを切り替える操作 -->
<button @click="changeComponent('Parent')">押したら親の名前が表示されます</button>
<br>
<button @click="changeComponent('Child')">押したら子供の名前が表示されます</button>
<hr>
<!-- compenentタグで動的にVueコンポーネントを切り替える -->
<component :is='currentComponents'></component>
</div>
</template>
<script>
import Parent from "./components/Parent.vue";
import Child from "./components/Child.vue";
export default {
data: function() {
return {
currentComponents: "Parent"
}
},
components: {
Parent: Parent,
Child: Child
},
methods:{
changeComponent: function(compName) {
this.currentComponents = compName
}
},
}
</script>
切り替え時のキャッシュ
なお、切り替えの度にVueインスタンスがdestroy
とcreate
を繰り返している。
インスタンスが消えてしまうため、dataが毎回削除(=初期化)されるということなので、注意が必要。
もしdestroy
させないためには(=キャッシュさせるためには)、keep-alive
タグを使う。
<!-- keep-aliveタグを使ってキャッシュ -->
<keep-alive>
<component :is='currentComponents'></component>
</keep-alive>
ただし、こうすると従来のライフサイクルメソッドのdestroyed()
が使えなくなる。
その代わりに、deactivated()
とactivated()
が使えるようになる。
deactivated()
:該当コンポーネントが表示されなくなった時にコールされる
activated()
:該当コンポーネントが表示された時にコールされる
<template>
<div>
<p>親の山田一郎です</p>
</div>
</template>
<script>
export default {
// keep-alive用
deactivated() {
console.log("deactivated:非表示になりました")
},
// keep-alive用
activated() {
console.log("activated:表示になりました")
}
}
</script>
8-9. コンポーネントでのv-model(propsとemit)
親コンポーネントにてv-model
を指定して、子コンポーネントでその値を反映するやり方は、
props
と$emit
をを両方使う。
type
によって、子コンポーネントのinput
タグの書き方が異なる。
テキストボックス
<template>
<div>
<!-- v-modelの指定 -->
<LastName v-model="defaultMsg"></LastName>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
defaultMsg: 'デフォルトメッセージ'
}
},
components: {
LastName: LastName
}
}
</script>
<template>
<div>
<p>私は{{name}}です</p>
<!-- valueにpropsの値を反映させ、 -->
<!-- $emitにinputメソッドを指定して発火させて親コンポーネントに反映させる -->
<input
id="title"
type="text"
:value="value"
@input="$emit('input', $event.target.value)"
>
<pre>{{ value }}</pre>
</div>
</template>
<script>
export default {
props: {
// v-modelの受け口として、valueという変数名で、propsを指定する
value: {
type: String,
required: true
}
},
data: function() {
return {
name: "山田",
}
}
}
</script>
チェックボックス
<template>
<div>
<!-- v-modelの指定 -->
<LastName v-model="defaultCheck"></LastName>
</div>
</template>
<script>
import LastName from "./components/LastName.vue";
export default {
data: function() {
return {
defaultAge: 15,
defaultCheck: true
}
},
components: {
LastName: LastName
}
}
</script>
<template>
<div>
<p>私は{{name}}です</p>
<!-- チェックボックスのchangeイベントを利用する -->
<!-- $emitにchangeメソッドを指定して発火させて親コンポーネントに反映させる -->
<input
type="checkbox"
:checked="childChecked"
@change="childChecked=$event.target.checked"
>
<pre>{{ childChecked }}</pre>
</div>
</template>
<script>
export default {
props: {
// valueという変数名で、propsを指定する
// チェックは、boolean
value: {
type: Boolean,
required: true
}
},
data: function() {
return {
name: "山田",
childChecked: this.value
}
}
}
</script>