見出し画像

setupシンタックスシュガーを使ってVue3のコンポーネントを書き換える

Vue2からVue3のComposition APIにコードを書き換える方法について以前↓で紹介した。

その後Vue3.2がリリースされた際、Composition APIを使ったコンポーネントの定義をより簡潔にする目的で<script setup>というシンタックスシュガーが提供されました。
Vueではロジックを<script></script>のタグの中に記述しますが、タグのなかにsetupという文字列を追加し、<script setup></script>とすることで、より簡潔な記法でComposition APIを使ったコンポーネントを記述できるようになったので紹介します。

まず、前回のブログのでは以下のVue3コンポーネントを完成させました。setup()関数の中にデータの定義、関数の定義をまとめたComposition APIの記法で記述されています。今回はこれを<script setup>シンタックスシュガーを使ったものに書き換えて行きたいと思います。

<script>
import { ref, computed, reactive } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';

export default {
  name: 'LatLng',

  setup() {
    const store = useStore();
    const router = useRouter();

    const latLngs = ref([]);
    const offset = ref(0);
    const limit = 5;
    const totalCount = ref(0);
    const currentLatLng = reactive({});
    const filter = reactive({
      age: true,
      hAcc: true,
      vAcc: true,
    });

    const isFirstPage = computed(() => {...});
    const isLastPage = computed(() => {...});    
    const latLngCreatedDatetime = computed(() => {...});
    
    const path = computed(() => store.state.path.path);
    const projects = computed(() => store.state.project.projects);

    const fetchNextLatLngs = async () => {
      ...
      fetchLatLngs();
    };

    const fetchPreviousLatLngs = async () => {
      ...
      fetchLatLngs();
    };

    const fetchLatLngs = async () => {...};

    const rowClicked = (latLng) => {...};

    onMounted(() => {
      fetchLatLngs();
    });

    return {
      //Variables
      latLngs,
      offset,
      limit,
      totalCount,
      currentLatLng,
      filter,
      
      //Computed
      isFirstPage,
      isLastPage,      
      latLngCreatedDatetime,
      
      //Store
      path,
      projects,

      //Methods
      fetchNextLatLngs,
      fetchPreviousLatLngs,
      fetchLatLngs,
      rowClicked,      
    };
  },
};
</script>


<script> → <script setup>に書き換える

まずはじめに、

<script>

を下のように書き買えます。

<script setup>

これでシンタックスシュガーが有効になります。

export defaultとコンポーネントの名前がいらなくなる


import文の次に来る以下の2行がいらなくなります。以下の部分を削除します。(export default {と対になっている } を消し忘れないように注意しましょう。)

export default {
  name: 'LatLng',

};


setup関数がいらなくなる

<script setup>シンタックスシュガーの一番の利点として、setup()関数の中にすべてを収めなくても良くなります。setup()の中に記述したコードを一旦カット&ペーストで、setup()関数の外側に出して貼り付け、setup()関数を削除しましょう。

 setup() {
    
  }, 


return { } を削除する

これでデータの定義、computed変数の定義、関数の定義などがsetup()の外にでた状態ですが、この次にreturn { }をごっそりと削除します。
setup()は関数なので、なかで定義したものを外にreturnする必要がありましたが、今これらの変数や関数の定義はコンポーネントのトップレベルに記述されています。returnの必要がなくなったので、下のreturn { }の部分を削除します。

    return {
      //Variables
      latLngs,
      offset,
      limit,
      totalCount,
      currentLatLng,
      filter,
      
      //Computed
      isFirstPage,
      isLastPage,      
      latLngCreatedDatetime,
      
      //Store
      path,
      projects,

      //Methods
      fetchNextLatLngs,
      fetchPreviousLatLngs,
      fetchLatLngs,
      rowClicked,      
    };

これで、完成です!
下が完成したコンポーネントのコードです。ものすごくシンプルになりましたね。Vue3.0のころからこのシンタックスでよかったんじゃないかと思うほどコンポーネントのコードがすっきりしました。

import { ref, computed, reactive } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';

<script setup>
const store = useStore();
const router = useRouter();

const latLngs = ref([]);
const offset = ref(0);
const limit = 5;
const totalCount = ref(0);
const currentLatLng = reactive({});
const filter = reactive({
  age: true,
  hAcc: true,
  vAcc: true,
});

const isFirstPage = computed(() => {...});
const isLastPage = computed(() => {...});    
const latLngCreatedDatetime = computed(() => {...});

const path = computed(() => store.state.path.path);
const projects = computed(() => store.state.project.projects);

const fetchNextLatLngs = async () => {
  ...
  fetchLatLngs();
};

const fetchPreviousLatLngs = async () => {
  ...
  fetchLatLngs();
};

const fetchLatLngs = async () => {...};

const rowClicked = (latLng) => {...};

onMounted(() => {
  fetchLatLngs();
});
</script>

<script setup>シンタックスシュガーではその他にも記述方法が変わったものがあるので、1つ1つ説明していきたいと思います。

アロー関数を使わない場合は、"function"というプレフィックスで定義できる。

上のサンプルではVue3に書き換えたときに関数をすべてアロー関数にしていたので、すべての関数がアロー関数になっていますが<script setup>シンタックスシュガーでは下のようにfunctionを使って関数を定義することもできます。


function rowClicked(latLng) {

  ...

}

async関数も下のようにfunctionの前にasyncをつけて定義できます。

async function searchSimilarQuotes() {

    ...

}

仕様するComponentを列挙しなくてよい。

今まではComponent内で別のComponentを使いたい場合はそのComponentをimportするとともにcomponents:に続いて、仕様するComponent名を列挙する必要がありました↓

import ButtonDropdown from '@/components/form/ButtonDropdown.vue';
import DateTimePicker from '@/components/form/DateTimePicker.vue';

export default {
  name: 'MyComponent',
  
  components: {
    ButtonDropdown,
    DateTimePicker,
  },

<script setup>シンタックスシュガーでは、components:の記述が必要なくなり、下のようにただimportするだけでよくなりました。

import ButtonDropdown from '@/components/form/ButtonDropdown.vue';
import DateTimePicker from '@/components/form/DateTimePicker.vue';


propsの使い方が変わった

propsはsetup関数の引数として受け取っていました。

  setup(props) {

setup関数がなくなり、propsへのアクセスは
definePropsをつかって取得するようになりました。definePropsの引数にpropsで取得する変数の名前(データのキー)と型を記述します。

const props = defineProps({
  item: Object,  
});

親コンポーネントからのデータの渡し方は今までと同じです。

<ItemEditCell :item="item"/>

definePropsを使うときは下のように、definePropsをvueライブラリからimportする必要があります。

import { ref, defineProps } from 'vue';

emitの使い方が変わった

同様にemitの使い方も変わりました。今までは下のようにcontext変数をsetup関数の引数で受け取り、その中のemit関数を使っていました。

 setup(props, context) {
   

    const closePopup = () => {      
      context.emit('popup_closed');
    };
}

あるいは、以下のようにcontextの中のemitだけを引数で受け取って使うこともできました。

  setup(props, { emit }) {

<script setup>シンタックスシュガーでは、defineEmitsを下のように使ってemitオブジェクトを取得します。引数にemitしたいイベントの名前のリストを渡します。

const emit = defineEmits([  
  'onItemUnfocused',
  'onItemFocusClosed',
  'onAddItemBelow',
  'onItemMoveUp',
  'onItemMoveDown',
]);

これで今までのようにemitが使えます。

<input type="text" @blur="$emit('onItemUnfocused')" />

defineEmitsを使うときは下のように、definePropsをvueライブラリからimportする必要があります。

import { ref, defineProps, defineEmits } from 'vue';


slotsもuseSlotsを使う

slotsもuseSlots()関数を使います。

import { useSlots } from 'vue';

const slots = useSlots();

const hasHeaderSlot = computed(() => !!slots.header);
const hasFooterSlot = computed(() => !!slots.footer);


<script setup>シンタックスシュガーを使うとコンポーネントのコード行数は確実に減ります。return { }の中に追加し忘れた変数や関数をビルド時に気づいて追加するなどという手間もなくなりプログラミング時のストレスもかなり軽減されると感じました。是非使ってみてください!


最後までお読みいただき、心から感謝申し上げます。この記事がお役に立ち、楽しんでいただけたなら、ぜひハートマークをクリックしていただくか、今後もこのようなWeb技術関連の記事に興味がある方は、アカウントのフォローをご検討ください。
皆様のサポートが私の大きな励みとなります!今後も有益な技術関連の情報を提供できるようエンジニア生活に勤しんでまいります!

このブログに関する質問やWebアプリ、iOS・Androidアプリの開発の相談はこちらから↓↓↓

@mizutory
mizutori@goldrushcomputing.com




いいなと思ったら応援しよう!