1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Composition API を触ってみた

Last updated at Posted at 2020-09-30

Composition API とは

公式ドキュメント

コンポーネントの柔軟な合成を可能にする関数ベースのAPIです
Composition Function によりロジックの関心ごとにコードをまとめやすくなるのと、
型推論の改善も組み込まれているようです。

以前はコンポーネントでロジックを使いまわしたい時は mixin を使う必要がありましたが、namespace の衝突の問題がありました。 ( this.~ )

今回はとりあえず Option API からの書き換えをメインに書きたいと思います。

開発環境

型推論 の機能もあるということで、 vue-cli で TypeScript 対応のプロジェクトを作成して試してみました
TypeScript 対応はこちらを参考にさせていただきました

$ vue create your-project-name
# オプションの class-style component は今回使わないので No にしました

Vue2系で Composition API を使うには @vue/composition-api が必要なのでインストールします

$ npm i @vue/composition-api

main.ts に 2 行追加します

import Vue from 'vue';
import App from './App.vue';
import VueCompositionApi from '@vue/composition-api'; // 追加

Vue.use(VueCompositionApi); // 追加
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
}).$mount('#app');

これで準備完了です!

Options API からの書き換え

Options API は Vue の基本的な記述法です
テンプレート/スタイル部分のコードは省略します!

props

  • こちらは特に変化なしですね
  • setup の第一引数で props を使用できます
  • setup はこのあと出てきますが、初期化を行うような関数です
export default {
  props: {
    list: {
      type: Array,
      default: [],
    },
  },
  setup(props){
  }
}

data

  • reactive を使って、 setup の中に定義します
    • props のように例外もありますが、基本 setup の中に定義していく感じです
  • setup で state を return します
  • state.{プロパティ名} で参照できます
import { reactive } from '@vue/composition-api';

export default {
  setup() {
    const state = reactive({ 
      items: [],
      newItem: ''
    });
    return { state }
  }
}

ですが、 ↓ のように toRefs を使うのがおすすめみたいです
こうすることで、テンプレート部分で state を介さず直接プロパティ名で参照できるようになります

import { reactive, toRefs } from '@vue/composition-api';

export default {
  setup() {
    const state = reactive({ 
      items: [],
      newItem: ''
    });
    return { ...toRefs(state) }
  }
}

computed

  • computed を使います
import { reactive, toRefs, computed } from '@vue/composition-api';

export default {
  setup() {
    const state = reactive({ 
      items: [],
      newItem: ''
    });
    
    const totalCount = computed(() => {
      return state.items.length;
    });

    return { ...toRefs(state), totalCount }
  }
}

methods

  • 普通に関数を定義するだけです、 return もお忘れなく
import { reactive, toRefs } from '@vue/composition-api';

export default {
  setup() {
    const state = reactive({ 
      items: [],
      newItem: ''
    });

    const addItem = () => {
      state.items.push(state.newItem);
      newItem = '';
    };

    return { ...toRefs(state), addItem }
  }
}

watch

  • watchEffect を使います
  • Option API の watch との違いは、 watchEffect の中で参照されているオブザーバブルな値が変更された場合に実行されます
import { reactive, toRefs, watchEffect } from '@vue/composition-api';

export default {
  setup() {
    const state = reactive({ 
      items: [],
      newItem: ''
    });

    watchEffect(() => {
      console.log(state.items);
    });

    return { ...toRefs(state) }
  }
}

emit

  • setup の第二引数 context を使って context.emit で実行
  • キャメルケース使用不可。ケバブケースで記述する必要あり
export default {
  setup(props, context) {
    context.emit('value-change');
}

ライフサイクルフック

  • on~ の形で使えます
import { onMounted } from '@vue/composition-api';

export default {
  setup() {
    onMounted(() => {
      console.log('mounted!');
    });
  }
}

型推論を効かせる

  • TypeScript で書く場合、 defineComponent で setup に渡された引数の型推論を効かせることができるようになります
  • props の型は PropType を使用します

例えばこんなコードの時

import { PropType, toRefs }

export default {
  props: {
    list: {
      type: Array as PropType<string[]>,
      default: [],
    },
  },
  setup(props) {
    const state = reactive<{ newItem: string }>({ newItem: '' });

    const addItem = () => {
      props.list.push(''); // <= 注目
      state.newItem = 0; // <= 注目
    };
    return { ...toRefs(state), addItem }
  }
}

まず state.newItem のほうは、 string 型に指定しているのでエラーになっています
型推論が効いていますね

props.list のほうは 型情報が不明になっていますね...

これに defineComponent を使用します(全体を囲うだけ)

import { defineComponent, PropType, toRefs }

export default defineComponent({
  props: {
    list: {
      type: Array as PropType<string[]>,
      default: [],
    },
  },
  setup(props) {
    const state = reactive<{ newItem: string }>({ newItem: '' });

    const addItem = () => {
      props.list.push('');
      state.newItem = 0;
    };
    return { ...toRefs(state), addItem }
  }
})

お、型情報がきましたね!

マイグレーションについて

Vue2 から Vue3 への マイグレーションは vue-codemod を使えば簡単にできるとのことですが、Option API から Composition API へのマイグレーションは、少なくとも今のところは手動でやるしかないみたいですね...

おわりに

今回は試せなかったのですが、 Composition Function も実装してみたいです。
おそらくここが Composition API の肝な気がする...

Composition Functionとは、関連するロジックでまとめられ、カプセル化された関数のことです。Composition APIによってthisへの依存がなくなり、コードは関心ごとでまとめられるようになりました。まとめられた関数は純粋なJavaScript or TypeScriptの関数として抽出し、他のコンポーネントで再利用しやすくなります。
https://techblog.zozo.com/entry/vue-options-api-to-composition-api#Composition-Function

1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?