LoginSignup
13
1

More than 1 year has passed since last update.

【Vue 3】コンポーネント間のデータの受渡し【基礎】

Last updated at Posted at 2021-04-29

1. はじめに  

1-1. はじめに

Vueのコンポーネント間のデータの受渡しが「親→子」「子→親」で異なり複雑です。
私の頭を整理するために、この記事を記載しています。

1-2. 説明の前に・・・

説明で使用するプログラム ( x.html, x.js ) は、下記の.htmlファイルに記載する前提での説明です。
また、記載はVue3ですが、基本的にVue2でも同じ考え方です。

index.html
<!DOCTYPE html>
<html lang="ja">
<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">
  <script src="https://unpkg.com/vue@next"></script>
  <title>vue sample</title>
</head>
<body>
  <div id="app">
      // **************************************
      // ここにx.htmlを記載
      // **************************************
  </div>
  <script>
      // **************************************
      // ここにx.jsを記載
      // **************************************
  </script>
</body>
</html>

2. コンポーネントの基礎

2-1. コンポーネントとは

コンポーネントは「名前付きの再利用可能なインスタンス」です。
2-1.jsのようにコンポーネントを定義し、2-1.htmlで定義したコンポーネントを3つ使用しています。
コンポーネントが再利用され、3つのボタンが表示されます。

2-1.html
<div id="app">
  <Counter></Counter>
  <Counter></Counter>
  <Counter></Counter>
</div>
2-1.js
// アプリケーションの生成
const app = Vue.createApp({})

// コンポーネントを定義 (第一引数:コンポーネントの名前, 第二引数:コンポーネントオブジェクト)
app.component('Counter',{
  data() {
    return {
      count : 0
    }
  },
  template: `
    <button v-on:click="count++"> コンポーネントだよ:{{count}} </button>
  `
})

// id="app" にマウント
app.mount('#app')

image.png

2.2 グローバルコンポーネントとローカルコンポーネント

コンポーネントには2種類あります。グローバルコンポーネントローカルコンポーネントです。

  • グローバルコンポーネント
    アプリケーションのcomponentメソッドを利用します。
    アプリケーション内のどのコンポーネントのテンプレートでも使用できます。
    2-1で定義したコンポーネントもグローバルコンポーネントです。
    実際はビルドの最適化を高めるために、ローカルコンポーネントで定義するほうが一般的です。   

  • ローカルコンポーネント
    オブジェクトを定義して、componentsオプションで登録します。 
    componentsで登録したコンポーネント内でのみ使用できます。

以下の例は、ローカルコンポーネントChildをグローバルコンポーネントParentcomponentsに登録しています。
Parentの中でのみChildが使用できるようになります。
この際、Parent親コンポーネント(以降、親)、Child子コンポーネント(以降、子)といいます。1

2-2.html
<div id="app">
  <Parent></Parent>
</div>
2-2.js
// アプリケーションの生成
const app = Vue.createApp({})

// ローカルコンポーネント+子コンポーネント
// オブジェクトを定義
const Child = {
  template: `
    <h2> Child ! </h2>
  `
}

// グローバルコンポーネント+親コンポーネント
app.component('Parent',{
  // コンポーネントの登録をする
  components: {
    Child
  },
  // 親コンポーネントの中で子コンポーネントは使用できる
  template: `
    <h1> Parent ! </h1>
    <Child></Child>
  `
})

// id="app" にマウント
app.mount('#app')

image.png

3. コンポーネント間のデータの受渡しの基礎

3-1. 親コンポーネントから子コンポーネントへのデータの受渡し

子にpropsオプションを定義します。親からデータを渡すときはhtmlの属性を使用するように渡すことができます。
基本的にVueでは親から子への単方向のデータフローです。
propsの定義の仕方を変えると、バリデーションも付けられます。

3-1.html
  <div id="app">
    <Parent></Parent>
  </div>
3-1.js
// アプリケーションの生成
const app = Vue.createApp({})

// 子コンポーネント
const Child = {
  // 親から受け取るdataを定義
  props:['parentData'],
  template: `
    <h2> Child ! </h2>
    <h2> {{parentData}} </h2>
  `
}

// 親コンポーネント
app.component('Parent',{
  components: {
    Child
  },
  // htmlの属性のように記載してデータを渡す
  template: `
    <h1> Parent ! </h1>
    <Child parentData="親コンポーネントから書き換え!"></Child>
  `
})

image.png

3-2. 子コンポーネントから親コンポーネントへのデータの受渡し

Vueは親から子への単方向データフローです。そのため、子から親へデータを受け渡すには少し工夫が必要です。

  1. $emitを使用して、子から親のイベントを発火させます。
  2. イベントで設定されたJavaScriptやメソッドを実行させ、その中で親のデータを変更します。
    データの受取り方法は2種類あります。$eventを使用する方法とメソッドの第一引数で受け取る方法です。
3-2.html
  <div id="app">
    <Parent></Parent>
  </div>
3-2.js
const app = Vue.createApp({})

// 子コンポーネント
const Child = {
  // $emitの第一引数はイベント名(childData)、第二引数は渡す値("親に渡すデータ")を定義
  template: `
    <button v-on:click='$emit("childData","親へ渡すデータ")'>親へデータ渡すボタン</button>
  `
}

// 親コンポーネント
app.component('Parent',{
  data() {
    return {
      eventData: '',  // $eventで渡したデータを格納
      methodData: '', // メソッドで渡したデータを格納
    }
  },
  components: {
    Child
  },
  // $eventを使用する方法とメソッドで渡す方法がある
  template: `
    <h1> Parent ! </h1>

    <h3>1. $eventを使用する方法</h3>
    <Child v-on:childData="eventData = $event"></Child>
    eventData : {{eventData}}

    <h3>2. メソッドで渡す方法</h3>
    <Child v-on:childData="changeParentData"></Child>
    methodData : {{methodData}}
  `,
  methods: {
    // methodの第一引数としてデータが渡される
    changeParentData(event) {
      this.methodData = event 
    }
  }
})

// id="app" にマウント
app.mount('#app')

image.png

4. おわりに

最後まで読んでいただきありがとうございました。今回の記事のポイントは以下です。

  • Vueは親コンポーネントから子コンポーネントへの単一方向のデータフローである。
  • 親→子:子でpropsを用いてデータを受け取る。
  • 子→親:子にて$emitを使用してイベントを起動。親にて$eventやメソッドでデータを受け取る。

記載の誤りや、文字の揺らぎがあるかもしれません。ご指摘がありましたらコメントいただけると幸いです。
詳細が知りたい方や、より正確な情報を知りたい方は参考URL(Vue3公式ページ)を参照してください。

参考URL


  1. 親はグローバルコンポーネント、子はローカルコンポーネントというルールはありません。componentsオプションを定義しているのが親、定義に使用されているのが子です。  

13
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
1