7839

雑草魂エンジニアブログ

Vue.jsエンジニアのReact入門 - コンポーネントの親子関係

Vue.js エンジニアの React 入門。
React の実装方法を Vue.js と対比しながら理解を深めていくシリーズ。

今回は、「コンポーネントの親子関係」である。

親子間でのデータのやり取り、イベントハンドリングを確認する。

Vue.js

まずは、Vue.js での実装方法から確認する。

f:id:serip39:20200712094629p:plain

親要素から子要素へのデータ受け渡しは、プロパティ propsで行う。子要素から親要素へのイベント通知は、 $emit メソッドを用いる。また、上図には記載していないが、親要素から子要素のメソッドを実行したい場合は、 ref を用いることで、子要素にアクセスすることができる。

<template>
  <div class="parent">
    <Child
      ref="child"
      color="red"
      :user="user"
      @submit="parentFunction"
    />
  </div>
</template>
<script>
import Child from 'src/components/child'
export default {
  data: () => ({ user: { name: '太郎', age: 20 } }),
  methods: {
    parentFunction(data) {
      // method
    },
    reset() { this.$refs.child.childFunction() }
  }
}
</script>
<template>
  <div class="child">
    <form>
      <input v-model="text">
      <button @click="$emit('submit', text)">send</button>
    </form>
  </div>
</template>
<script>
export default {
  props: {
    color: { type: String, default: 'white' }
    user: { type: Object, default: () => ({}) }
  },
  data: () => ({ text: '' }),
  methods: {
    childFunction(data) {
      // method
    }
  }
}
</script>

React

Reactの場合は、データやイベントを区別することなく、プロパティを指定することで同様のことが実現できる。子要素では、 props を用いてそれぞれのプロパティにアクセスできる。

import React from 'react'
import Child from './components/Child'
const App = () => {
  const user = { name: '太郎', age: 20 },
  const parentFunction = (data) => {  //method },
  return (
    <Child
      color="red"
      user={user}
      onSubmit={parentFunction}
    />
  )
}
export default App
import React from 'react'
const Child = (props) => {
  // props.color
  // props.user
  // props.onSubmit(data)
}
export default Child

Vue.js 同様に、プロパティのバリデーションなどを行いたい場合は、 prop-types ライブラリを用いる。

また、Vue.js には、レイアウトのテンプレート機能を実現できる slot という便利なメソッドがあった。

Vue.js

name のない slot 要素は、暗黙的に「default」という名前を持つ。名前付きスロットにコンテンツを指定するには、<template>に対して v-slot ディレクティブを使って、スロット名を引数として与える。defaultの場合は、<template>を使って明示しなくても問題ない。

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>
  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

スロット — Vue.js

React

Reactの場合は、プロパティの children を用いて、要素の受け渡しを行うことができる。ただし、上記のような名前指定をしての挿入をする場合は、以下のように独自のプロパティで React コンポーネントを受け渡しすることで実現できる。

const BaseLayout = (props) => {
  return (
    <div className="wrapper">
      <header>{props.header}</header>
      <main>{props.content}</main>
      <footer>{props.footer}</footer>
    </div>
  )
}
export default BaseLayout
import React from 'react'
import BaseLayout from './components/baseLayout.jsx'
import Header from './components/header.jsx'
import Content from './components/content.jsx'
import Footer from './components/footer.jsx'
const App = (BaseLayout) => {
  return (
    <BaseLayout
      header={<Header />}
      content={<Content />}
      footer={<Footer />}
    />
  )
}
export default App

コンポジション vs 継承 – React

まとめ

コンポーネントの親子関係についてまとめを行った。Vue.js は様々なメソッドがあるのに対して、React の場合はシンプルな構成になっていると思えた。

それでは、ステキな開発ライフを。