Vueのコンポーネント作成（基礎）

久しぶりにvueでコード書いたら、いろいろドンづまったのでメモ

## 箱型を作成
まずは最もシンプルなvueを作成します。
しばらくはjavascriptをHTMLと同じファイルに作成します。

``````html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>vueを学ぶ</title>
</head>

<body>
  <div id="app">
    {{perfume[0].name}}
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
})
</script>
</body>
</html>
``````

ブラウザで開くと、"かしゆか"だけ表示されます。

## グローバル子コンポーネントを作成

次に子コンポーネントを作成します。（まずはグローバルから）
子コンポーネントは、以下のような形です。
"component-name"はケバブ方式で書きましょう（大文字を入れるとエラーを起こします）

``````JavaScript
Vue.component('component-name',{
  template:"",
  props:""
})
``````

こちらが作成例です。

``````html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>vueを学ぶ</title>
</head>

<body>
  <div id="app">
    {{perfume[0].name}}

+    <perfume-member></perfume-member>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
+Vue.component('perfume-member',{
+  template:"<h1>コンポーネント</h1>"
+}
+)

new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
})
</script>
</body>
</html>
``````

## 親コンポーネントからデータを渡す
親コンポーネントからデータを渡すには、
[html側] v-bindでデータの受け渡しを記述
v-bindは左に子コンポーネントでのデータ名、右側に親コンポーネントでのデータ名です。
`<perfume-member v-bind:members="perfume"></perfume-member>`

[js側] 子コンポーネントはpropsで受け取る。

``````html
props:{
  members:""
}
``````

ここまでのコードです。
子コンポーネントのtemplateの部分は受け取ったデータを表示させるために
`"<h1>{{member[1].name}}</h1>"`と書き換えました

``````html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>vueを学ぶ</title>
</head>

<body>
  <div id="app">
    {{perfume[0].name}}

 +   <perfume-member v-bind:member="perfume"></perfume-member>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('perfume-member',{
+  template:"<h1>{{member[1].name}}</h1>",
+  props:{
+      members:"",
+    }
  }
)

new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
})
</script>
</body>
</html>
``````

![IMAGE](quiver-image-url/CD457BE6C7AC29C0B5648CB27988A78D.jpg =194x97)

## templateをx-templateに
現実のプログラムでは、templateを子コンポーネント内に直接記載することはまずなく、別ファイルに保管します。

[子コンポーネント] templateプロパティを`template:"#templateのid名"`にします。
[x-template]テンプレートファイルを作成します。
（ちなみにxとは、標準化されてないMIMEタイプに慣習的に付けられる名前です）

こんな感じで作成しました。
**注意！！** x-templateの中身は`<div>〜</div>`などタグで囲む必要があります。
（囲んでなかった時には、以下のようなエラーメッセージが出ます。one root elementって要は一つのDOM要素って意味なんですね）
「[Vue warn]: Error 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.」）

``````javascript
<script type="text/x-template" id="perfume-detail">
  <div>
    <h1>Perfumeのメンバー</h1>
    <ul>
      <li v-for="member in members">{{member.name}}</li>
    </ul>
  </div>
</script>
``````

x-templateの記述は子コンポーネントより前にする必要があります。
（後にすると、x-templateがありませんとエラーがでます）

ここまでのコードはこちら。

``````html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>vueを学ぶ</title>
</head>

<body>
  <div id="app">
-    {{perfume[0].name}} //もう不要なので消します 
-
    <perfume-member v-bind:members="perfume"></perfume-member>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

+<script type="text/x-template" id="perfume-detail">
+    <h1>Perfumeのメンバー</h1>
+    <ul>
+      <li v-for="member in members">{{member.name}}</li>
+    </ul>
+</script>

<script>
Vue.component('perfume-member',{
  template:"#perfume-detail",
  props:{
      members:"",
    }
  }
)

new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
})
</script>

</body>
</html>
``````

![IMAGE](quiver-image-url/89830271FDD37ACF7D4E1852D974282B.jpg =308x204)

## 子コンポーネントをローカル化

[親コンポーネント] componentsプロパティを追加

``````javascript
components:{
  "コンポーネント名":コンポーネント関数名
}
``````
[子コンポーネント ]Vue.componentを削除し、ローカル関数として定義する

``````html
const コンポーネント名={
　template:・・・
}
``````

コードはこんな感じです
（scriptタグ内のみを抜粋）

``````html
<script>
-Vue.component("perfume-member",
+const perfume={
  template:"#perfume-detail",
  props:{
      members:"",
    },
  }

new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
+ components:{
+   "perfume-member":perfume,
+ }
})
</script>
``````

## 子コンポーネントのデータ設定
親から受け取らず、子コンポーネント独自に定めるデータの記述方法です。
dataプロパティはfunctionでオブジェクトを返すようにします。
（アロー関数を使った書き方もできます）

``````JavaScript
  data:()=>{
    return {
      songs:[{title:"TOKYO GIRL"},{title:"Spring of Life"},{title:"FLASH"}]
      }
    }
``````
コード全体です。
x-templateにはdataを表示させるようにしました。

``````html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>vueを学ぶ</title>
</head>

<body>
  <div id="app">
    <perfume-member v-bind:members="perfume"></perfume-member>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script type="text/x-template" id="perfume-member">
  <div>
    <h1>Perfume</h1>
    <h2>メンバー</h2>
    <ul>
      <li v-for="member in members">{{member.name}}</li>
    </ul>
+    <h2>曲</h2>
+    <ul>
+      <li v-for="song in songs">{{song.title}}</li>
+    </ul>
  </div>
</script>

<script>
const perfume={
  template:"#perfume-member",
  props:{
      members:"",
    },
+  data:()=>{
+    return {
+      songs:[{title:"TOKYO GIRL"},{title:"Spring of Life"},{title:"FLASH"}]
+      }
+    }
}

new Vue({
  el: '#app',
  data: {
    perfume: [{name:"かしゆか"},{name:"あ〜ちゃん"},{name:"のっち"}]
  },
  components:{
    "perfume-member":perfume,
  }
})
</script>

</body>
</html>
``````

![IMAGE](quiver-image-url/D21577FE1097424ABD9ABE962A692D2F.jpg =209x354)