コンポーネント分割についての説明 - orimajp/nuxt-simple-todo-study Wiki

Original URL: https://github.com/orimajp/nuxt-simple-todo-study/wiki/コンポーネント分割についての説明

コンポーネント分割についての説明

ここでは、ステップ1で作成したシンプル構成版アプリを元にコンポーネント分割版アプリに変更するために必要となる、親コンポーネントと子コンポーネント間におけるデータ及びイベント連携方法について説明します。

コンポーネントの特徴

コンポーネントはページコンポーネントとほぼ同じ内容の記述が可能で、以下の部分のみ違いがあります。

レイアウト指定不可

ページコンポーネントでは何も指定しない場合、デフォルトのレイアウトとしてlayoutsフォルダのdefault.vueが使用されますが、layoutプロパティにより別のレイアウトファイルを指定可能です。

コンポーネントはページコンポーネントに組み込まれるため、レイアウトを指定できません。

components配下に格納

pagesフォルダ配下に格納するページコンポーネントと異なり、componentsフォルダ配下に格納します。

同じ拡張子であっても格納フォルダで役割が異なるのはNuxt.jsの動作によるもので、Vue.js単独利用時は格納フォルダによるファイルの暗黙的な役割設定は行われない。

親子間のデータ連係

親子間のデータ連係方法は複数ありますが、今回は親から子はデータ連係、親から子はイベント通知という方法をとります。

親から子へのデータ連係

子コンポーネントでの記述

親コンポーネントから渡されるデータをpropsプロパティに定義します。

  props: {
    toDoItems: {
      type: Array as PropType<Array<ToDoItem>>, // 型定義はPropTypeで行う
      require: true, // 必須フラグ
      default: () => [], // デフォルト値。requireの場合は必須では無いが、ESLintのワーニングが出るので記述
    },
  },
  setup() {}

typeは、パラメータの型によって決まり、ArrayでないオブジェクトではObjectとしたりします。

なお、ESLintのワーニングは抑制記述(?)により抑えることができ、上記でデフォルト値を省略した場合のワーニングは、// eslint-disable-next-line vue/require-default-propというコメント行を対象のプロパティtoDoItemsの前に追加すればOKです。

VS codeのVetureプラグインのバグ回避策

こちらの記事によると、現時点で、VS codeのVetureプラグインにバグがあり、外部定義の型をPropTypeで指定するとエラーになるとのこと。これに対して以下のような回避策があるようです。

type: Array as () => Array<ToDoItem>,

親コンポーネントでの記述

親コンポーネントでは、子コンポーネントタグに以下のように記述することで、親コンポーネントでreturnしたデータを子コンポーネントのデータにバインドします。

<to-do-list :to-do-Items="toDoItems" />

上記において、to-do-Itemsは、子コンポーネントのpropsで定義したデータ名をケバブケースで記述します。toDoItemsは親コンポーネントのreturnで返した変数名を記述します。

子から親へのイベント通知

子コンポーネントから親コンポーネントへの連携はイベント通知により行います。

子コンポーネントでの記述

setup関数の第二引数に渡されるcontextオブジェクトのemit関数を利用することで、親コンポーネントのイベントを呼び出します。

setup(_, context) { // 第二引数だけ使う場合、第一引数を'_'と記述することで利用しないことを明示する。
  const addToDo = (toDoItem: ToDoItem) {
    context.emit('addNewToDo', toDoItem) // addNewToDoが呼び出すイベント
  }

  return {
    addToDo
  }
}

自身が定義していないデータ型を知る方法

TypeScriptによるコーディングを行っている場合、前述のcontext等の型が分からない値を関数パラメータとして利用する際に、型定義エラーになってしまいます。

ググったりすることもできなくは無いですが、検索条件が曖昧でノイズが多く調査が難しいことがあります。このような場合、エディタ上でcontextにマウスカーソルを当てると型定義を見ることができます。ただし、使っているエディタがTypeScriptに対応していなかったり、npm installしてなかったり、正しくプロジェクトを認識できていない場合は、参照できません。

また、型定義の詳細を知りたい場合、(エディタによっては?)定義位置にジャンプして参照できる場合があります。飛び先はnode_modulesの*.d.tsファイルになります。

contextのデータ型SetupContextの型定義は以下にあるようです。中を見るとemitの関数定義なども書かれており、それ以外も含め型定義方法を勉強することもできます。

/node_modules/@vue/composition-api/dist/index.d.ts

親コンポーネントでの記述

親コンポーネントでは、子コンポーネントタグに以下のように記述することで、親コンポーネントでreturnした関数を子コンポーネントのイベントにバインドします。

<new-to-do-field @addNewToDo="addToDoItem" />

上記において、addNewToDoは子コンポーネントのemitで定義されたイベント、addToDoItemは親コンポーネントでreturnした関数です。