スロット、ミックスイン、CompositionAPIを使用してVue.jsアプリケーションをドライにする方法

提供:Dev Guides
移動先:案内検索

著者は、 Write for DOnations プログラムの一環として、 Open Sourcing MentalIllnessを選択して寄付を受け取りました。

序章

DRY は、「Don'tRepeatYourself」の略であるプログラミング戦略です。 コードが繰り返されるのではなく再利用されるモジュラーアーキテクチャを通じて、コードの再利用を促進します。 これにより、動的でスケーラブルなコードが得られることがよくあります。 つまり、この原則は、プログラマーがコードを繰り返したり、アプリケーションで値をハードコーディングしたりしないようにするためのものです。

Vue.js には、コードの繰り返しスニペットをモジュール化して再利用するためのいくつかの戦略が含まれています。 このチュートリアルでは、サンプルのVue.jsアプリケーションをDRYにして、これらの戦略を試してみます。 チュートリアルでは、templateおよびscriptDRYをコンポーネント内に保持する方法を紹介します。 slotsを介してコンテンツを配置できるHTML構造を確立するレイアウトコンポーネントを使用します。 次に、 mixins を使用します。これは、既存のコンポーネントオプションと混合するdatamethods、およびcomputedプロパティを含むJavaScriptファイルです。 最後に、Vue3で導入された新しいCompositionAPIを使用します。 Composition APIは、コンポーネントを構造化するための別の方法であり、コンポーネントのプロパティの統合を促進します。

前提条件

ステップ1—サンプルアプリケーションのセットアップ

スケーラブルでDRYVue.jsコードを作成する方法を説明するために、最初にサンプルアプリケーションをセットアップします。 このサンプルアプリケーションは、空港カードのリストを表示するメイン/詳細アプリケーションになります。 クリックすると、これらのカードは、その空港に関する追加の詳細を含む別のビューに移動します。

まず、新しいVue.jsアプリケーションを作成する必要があります。 これを行うには、ターミナルで次のコマンドを実行します。

vue create favorite-airports

プロンプトが表示されたら、Manually select featuresを選択します。 選択するオプションは、Choose Vue versionBabel、およびRouterです。 選択したら、RETURNキーを押して、次のようにプロンプトに入力し続けます。

OutputVue CLI v4.5.15
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, Router
? Choose a version of Vue.js that you want to start the project with 3.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files

favorite-airportsプロジェクトが作成されたら、ターミナルウィンドウを開き、cd(ディレクトリの変更)をfavroite-airportsルートフォルダーに移動します。 ディレクトリを変更したら、このプロジェクトのすべてのローカルデータを保持する新しいディレクトリを作成します。

mkdir src/data

このフォルダー内に、src/data/airports.jsという名前の新しいJavascriptファイルを作成し、選択したテキストエディターで開きます。 アプリにサンプルデータを提供するには、次のコンテンツをファイルに追加します。

お気に入り-airports/src / data / airports.js

export default [
  {
    name: 'Cincinnati/Northern Kentucky International Airport',
    abbreviation: 'CVG',
    city: 'Hebron',
    state: 'KY',
    destinations: {
      passenger: [ 'Toronto', 'Seattle/Tacoma', 'Austin', 'Charleston', 'Denver', 'Fort Lauderdale', 'Jacksonville', 'Las Vegas', 'Los Angeles', 'Baltimore', 'Chicago', 'Detroit', 'Dallas', 'Tampa' ],
      cargo: [ 'Anchorage', 'Baltimore', ' Chicago' , 'Indianapolis', 'Phoenix', 'San Francisco', 'Seattle', 'Louisville', 'Memphis' ]
    }
  },
  {
    name: 'Seattle-Tacoma International Airport',
    abbreviation: 'SEA',
    city: 'Seattle',
    state: 'WA',
    destinations: {
      passenger: [ 'Dublin', 'Mexico City', 'Vancouver', 'Albuquerque', 'Atlanta', 'Frankfurt', 'Amsterdam', 'Salt Lake City', 'Tokyo', 'Honolulu' ],
      cargo: [ 'Spokane', 'Chicago', 'Dallas', ' Shanghai', 'Cincinnati', 'Luxenbourg', 'Anchorage', 'Juneau', 'Calgary', 'Ontario' ]
    }
  },
  {
    name: 'Minneapolis-Saint Paul International Airport',
    abbreviation: 'MSP',
    city: 'Bloomington',
    state: 'MN',
    destinations: {
      passenger: [ 'Dublin', 'Paris', 'Punta Cana', 'Winnipeg', 'Tokyo', 'Denver', 'Tulsa', 'Washington DC', 'Orlando', 'Mexico City' ],
      cargo: [ 'Cincinnati', 'Omaha', 'Winnipeg', 'Chicago', 'St. Louis', 'Portland', 'Philadelphia', 'Milwaukee', 'Ontario' ]
    }
  }
]

これは、米国内のいくつかの空港で構成されるオブジェクト配列です。 このアプリケーションのメインビューでは、このデータを反復処理して、name abbreviationcity、およびstateで構成されるカードを生成します。プロパティ。

data/airports.jsを保存して、ターミナルに戻ります。

その手順が完了したら、AirportCard.vueという名前の単一ファイルコンポーネント(SFC)を作成します。 このファイルは、プロジェクトのcomponentsディレクトリにあり、空港カードのすべてのスタイルとロジックが含まれています。 テキストエディタでAirportCard.vueを開き、以下を追加します。

お気に入り-airports/src / components / AirportCard.vue

<template>
  <div class="airport">
    <p>{{ airport.abbreviation }}</p>
    <p>{{ airport.name }}</p>
    <p>{{ airport.city }}, {{ airport.state }}</p>
  </div>
</template>

<script>
export default {
  props: {
    airport: {
      type: Object,
      required: true
    }
  }
}
</script>

<style scoped>
.airport {
  border: 3px solid;
  border-radius: .5rem;
  padding: 1rem;
  margin-bottom: 1rem;
}

.airport p:first-child {
  font-weight: bold;
  font-size: 2.5rem;
  margin: 1rem 0;
}

.airport p:last-child {
  font-style: italic;
  font-size: .8rem;
}
</style>

このコードスニペットにCSSが含まれていることに気付くかもしれません。 AirportCard.vueコンポーネントでは、ラッパー<div>airportのクラスが含まれています。 このCSSは、各空港に「カード」の外観を与えるために境界線を追加することにより、生成されたHTMLにスタイルを追加します。 :first-child:last-childは、<div>内のHTMLの最初と最後の<p>タグに異なるスタイルを適用する疑似セレクターです。 airportのクラスを持つ要素。 それに加えて、このコンポーネントには prop が含まれていることに気付くかもしれません。これは、Vue.jsでは親コンポーネントから子コンポーネントにデータを渡す方法です。

ファイルを保存して終了します。

この設定を完了する前に、既存のviews/Home.vueコンポーネントコードを次のように置き換えます。

お気に入り-airports/src / views / Home.vue

<template>
  <div class="wrapper">
    <div v-for="airport in airports" :key="airport.abbreviation">
      <airport-card :airport="airport" />
    </div>
  </div>
</template>

<script>
import allAirports from '@/data/airports.js'
import AirportCard from '@/components/AirportCard.vue'

export default {
  components: {
    AirportCard
  },
  data() {
    return {
      airports: allAirports
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-column-gap: 1rem;
  max-width: 960px;
  margin: 0 auto;
}

p,
h3 {
  grid-column: span 3;
}
</style>

このコードには、v-forループが含まれています。このループは、airports.jsデータを反復処理し、プロップ:airportを介して渡された空港データを使用して一連のAirportCards.vueコンポーネントをレンダリングします。 ]。 このコードを保存して、コマンドラインに戻ります。

プロジェクトをセットアップしたら、ターミナルでnpm run serveコマンドを使用してローカル開発サーバーを実行します。

npm run serve

これにより、localhostで、通常はポート8080でサーバーが起動します。 選択したWebブラウザーを開き、localhost:8080にアクセスして、以下を確認します。

サンプルアプリケーションがセットアップされたので、次のステップでは、後でページレイアウトとして使用できる2つの異なるVue.jsコンポーネントを作成します。

ステップ2—slotを使用してレイアウトコンポーネントを作成する

レイアウトコンポーネントは、slot要素を使用して、さまざまなコンテンツで再利用できるHTMLテンプレートを作成するコンポーネントです。 これらは、2列または3列のレイアウトなど、再利用したい複数のテンプレートがある場合に最適です。

レイアウトコンポーネントを作成するには、最初にそれらが存在するディレクトリを作成します。 それらをcomponentsフォルダーに入れることもできますが、これらのコンポーネントには非常に特殊な役割があるため、それらを区別すると、プロジェクトは他のプログラマーにとって読みやすくなります。 srcディレクトリにlayoutsというディレクトリを作成します。

mkdir src/layouts

次に、layoutsディレクトリにDefaultLayout.vueという名前のファイルを作成します。 DefaultLayout.vueコンポーネントは、ビューのコンテンツを含み、ブラウザーウィンドウの中央に配置するラッパーになります。 テキストエディタでDefaultLayout.vueを開き、以下を追加します。

お気に入り-airports/src / layouts / DefaultLayout.vue

<template>
  <div class="default-layout">
    <slot />
  </div>
</template>

<style scoped>
  .default-layout {
    max-width: 960px;
    margin: 0 auto;
  }
</style>

このコンポーネントは、default-layoutのクラスを持つdivです。 このクラスを利用して、いくつかのスタイルを追加できます。 上記のコンポーネントに表示されるCSSスタイルは、その幅を最大960pxに制限し、サイドマージンは自動的に設定されます。 これにより、divがブラウザウィンドウの水平方向に中央揃えになります。 slot要素はデフォルトのスロットです。 2つの<layout-default>タグの間に配置されたものはすべて、この<slot />がある場所に注入されます。 前の手順で変更したHome.vueをリファクタリングすることで、これを試すことができます。

DefaultLayout.vueファイルを保存します。 テキストエディタで、src/views/Home.vueおよびimportDefaultLayout.vueコンポーネントを開きます。

お気に入り-airports/src / views / Home.vue

...
<script>
import allAirports from '@/data/airports.js'
import AirportCard from '@/components/AirportCard.vue'
import DefaultLayout from '@/layouts/DefaultLayout.vue'

export default {
  components: {
    AirportCard,
    DefaultLayout
  },
  data() {
    return {
      airports: allAirports
    }
  }
}
</script>
...

DefaultLayout.vueコンポーネントがインポートされたので、含まれている<div /><default-layout />に置き換えることができます。

お気に入り-airports/src / views / Home.vue

<template>
  <default-layout class="wrapper">
    <div v-for="airport in airports" :key="airport.abbreviation">
      <airport-card :airport="airport" />
    </div>
  </default-layout>
</template>
...

divを含む.wrapperクラスのmax-widthおよびmarginプロパティを削除できるようになりました。 このファイルを保存し、ブラウザウィンドウでlocalhost:8080を開きます。 視覚的には何も変更されませんが、中央に配置されたdivにコンテンツを含めるための新しいレイアウトコンポーネントができました。

次の手順に進む前に、もう1つのレイアウトコンポーネントを作成します。 これは2列のレイアウトになります。 1つの列は補足情報用で、もう1つの列はビューのメインコンテンツ用です。 src/layouts/TwoColumnLayout.vueに新しいファイルを作成します。 作成したら、テキストエディタでTwoColumnLayout.vueコンポーネントを開き、次を追加します。

お気に入り-airports/src / layouts / TwoColumnLayout.vue

<template>
  <div class="two-column-layout">
    <aside>
      <slot name="sideBar" />
    </aside>
    <main>
      <slot name="content" />
    </main>
  </div>
</template>

<style>
  .two-column-layout {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-column-gap: 1rem;
  }

  .two-column-layout aside,
  .two-column-layout main {
    border: 1px solid;
    border-radius: 5px;
  }

  .two-column-layout aside {
    grid-column: span 1;
  }

  .two-column-layout main {
    grid-column: span 2;
  }
</style>

このコンポーネントには、サイドバー用とメインコンテンツ用の2つの名前付きスロットがあります。 含まれている<div>で、CSSを使用して3つの列のグリッドを作成し、1つは1つの列に、もう1つは2つの列にまたがっています。

このレイアウトを使用するには、src/views/AirportDetail.vueで空港詳細ビューの新しいビューを作成してから、次のコードを新しいファイルに追加します。

お気に入り-airports/src / views / AirportDetail.vue

<template>
  <two-column-layout>
    <template v-slot:sideBar>
      <p>Sidebar</p>
    </template>
    <template v-slot:content>
      <p>Main Content</p>
    </template>
  </two-column-layout>
</template>

<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'

export default {
  components: {
    TwoColumnLayout
  },
}
</script>

この新しいビューはTwoColumnLayout.vueをインポートし、v-slotを使用して、指定されたスロットを適切なコンテンツで埋めます。

このファイルを保存します。 このビューを表示可能にするには、 Vuerouterファイルにルートを追加します。

お気に入り-airports/src / router / index.js

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import AirportDetail from '../views/AirportDetail'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/airport/:code',
    name: 'AirportDetail',
    component: AirportDetail
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]
...

ここでは、訪問時にAirportDetail.vueコンポーネントをロードするルートを登録しています。 path:codeは、後で特定の空港のデータを取得するために利用できる引数です。

ファイルを保存し、ブラウザを開いてlocalhost:8080/airport/cvgにします。 あなたは以下を見つけるでしょう:

このステップでは、スロットを利用してレイアウトコンポーネントを作成しました。 これらのレイアウトコンポーネントは、ウェブページの構造を作成するときに重複するコードを排除することで、アプリをドライに保つのに役立ちます。 次のステップでは、コンポーネント間でメソッドとプロパティを共有するためにミックスインを試してみます。

ステップ3—ミックスインを使用してメソッドとプロパティを共有する

ミックスインは、再利用可能なコンポーネントオプションを任意の数のコンポーネントに再配布する方法です。 ミックスインがインポートされると、ミックスインのコンポーネントオプションが現在のコンポーネントに「ミックスイン」されます。 これを説明するために、このステップでは最初にミックスイン構文の例を実行し、次にミックスインをサンプルアプリに追加します。

一意のプロパティを持つ2つのファイルがあるとします。 1つ目は、dataメソッドと、次のような計算プロパティを備えています。

サンプルコンポーネント

<script>
  export default {
    data() {
      return {
        firstName: 'Dave',
        lastName: 'Berning'
      }
    },
    computed: {
      fullName() {
        return `${this.firstName} ${this.lastName}`
      }
    }
  }
</script>

2つ目は、再利用したいいくつかのコンポーネントオプションを含むファイルです。

someMixin

export default {
  data() {
    return {
      counter: 0
    }
  },
  methods: {
    increment() {
      this.counter++
    }
  }
}

ミックスイン(someMixin)をコンポーネント(sample-component)にインポートすることにより、これら2つのファイルを一緒にミックスできます。 この架空のコンポーネントでは、importキーワードを使用してインポートし、mixinプロパティを使用して割り当てます。

サンプルコンポーネント

<script>
import someMixin from '@/mixins/someMixin'
      
export default {
  data() {
    return {
      firstName: 'Dave',
      lastName: 'Berning'
    }
  },
  mixins: [ 'someMixin' ],
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`
    }
  }
}
</script>

インポートされると、架空のコンポーネントは、すべてのmethodsdatacomputedプロパティ、およびコンポーネントに含まれる可能性のあるその他のコンポーネントオプションにアクセスできます。

次に、methodプロパティとdataプロパティを含むミックスインを作成します。 この関数は、空港nameabbreviationを組み合わせて、dataプロパティに格納します。

ターミナルで、mkdirコマンドを使用して新しいディレクトリを作成します。

mkdir src/mixins

src/mixins/airport.jsおよびexportという名前のファイルを、次のプロパティを含むオブジェクトにします。

src / mixins / airport.js

export default {
  data() {
    return {
      airportWithCode: ''
    }
  },
  methods: {
    getAirportWithCode(airport) {
      this.airportWithCode = `${airport.name} - ${airport.abbreviation}`
    }
  }
}

このオブジェクトにはdataメソッドが含まれ、メソッドはデータを空港の名前と略語に設定します。 このファイルを保存します。

これを作成したら、Home.vueビューにインポートします。 このmethodおよびdataプロパティを利用して、ユーザーがカードをクリックしたときに返される文字列を表示します。

src / views / Home.vue

<template>
  <default-layout class="wrapper">
    <div v-for="airport in airports" :key="airport.abbreviation" @click="getAirportWithCode(airport)">
      <airport-card :airport="airport" />
    </div>
    <p>test: {{ airportWithCode }}</p>
  </default-layout>
</template>

<script>
import allAirports from '@/data/airports.js'
import AirportCard from '@/components/AirportCard.vue'
import DefaultLayout from '@/layouts/DefaultLayout.vue'
import airportMixin from '@/mixins/airport.js'

  export default {
    components: {
      AirportCard,
      DefaultLayout
    },
    mixins: [ airportMixin ],
    data() {
      return {
        airports: allAirports
      }
    }
  }
</script>
...

そのミックスイン内のmethodsdataにアクセスできるので、他のコンポーネントオプションと同じようにそれらを参照できます。 このコードスニペットでこれを実行して、ユーザーがカードをクリックしたときにairportWithCode値を格納し、段落要素に文字列値をレンダリングします。 ファイルを保存します。

次に、この同じミックスインをAirportDetail.vueで再利用します。 テキストエディタでAirportDetail.vueを開き、JavaScript filterを記述して、abbreviation:code引数と一致する場合にairportオブジェクトを返します。以前にルーターで定義されました:

src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
  
export default {
  components: {
    TwoColumnLayout
  },
  data() {
    return {
      airport: ''
    }
  },
  methods: {
  getAirportByCode() {
    return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }
  },
  mounted() {
    this.airport = this.getAirportByCode()
  }
}
</script>

このスニペットでは、getAirportByCodeという名前の新しいmethodを作成しています。このスニペットは、空港データをフィルタリングし、ルートURLの略語と一致する空港オブジェクトを返します。 マウント時に、返されるオブジェクトにairportデータプロパティを割り当てます。

ファイルを保存します。 次に、前に使用したミックスインをインポートします。 以前と同じdataおよびmethodプロパティを活用します。

src / views / AirportDetail.vue

<template>
  <two-column-layout>
    <template v-slot:sideBar>
      <p>Sidebar</p>
    </template>
    <template v-slot:content>
      <p>Main Content</p>
      <p>{{ airportWithCode }}</p>
    </template>
  </two-column-layout>
</template>

<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import airportMixin from '@/mixins/airport.js'

export default {
  components: {
    TwoColumnLayout
  },
  mixins: [ airportMixin ],
  data() { ... },
  methods: { ... },
  mounted() {
    this.airport = this.getAirportByCode()
    this.getAirportWithCode(this.airport)
  }
}
</script>

getAirportByCode()で特定の空港を決定し、それをthis.airportに設定したので、getAirportWithCodeメソッドを使用して、からairportWithCodeの値を設定できます。混入します。 次に、その変数をテンプレートに追加して値を表示できます。

このファイルを保存し、ブラウザウィンドウでlocalhost:8080/airport/cvgを開きます。 次の画像に示すように、メインコンテンツセクションにレンダリングされたairportWithCodeの文字列値が表示されます。

このステップでは、ミックスインを使用して、コンポーネント間でメソッドと計算されたプロパティを共有しました。 ミックスインは、コンポーネントを整理し、アプリケーション全体で再利用可能なコードを活用するための優れた方法です。 次に、新しいComposition API、それが作成された理由、および次のVueアプリケーションの構成を改善する方法について学習します。

ステップ4—コンポジションAPIを使用する

このチュートリアルでこれまでに試したミックスインとレイアウトコンポーネントは、Vue2以前を含むVueのすべてのメジャーバージョンで使用できます。 これらはオプションAPIを構成します。 ただし、Vue 3には、アプリケーションをDRYにするために使用できる別のAPIがあります。CompositionAPIです。

Composition APIは、コンポーネントを設定するための新しい方法です。 datacomputedmethods、およびpropsに個別のセクションを設ける代わりに、すべてが存在する単一のsetupフックがあります。 。 このsetupプロパティ内では、コンポーネントが作成される前にコンポーネントが動作するために必要なすべてのものがここに入ります。 さらに、OptionsAPIでオプションを定義するために必要なすべてのものをインポートする必要があります。 しかし、これはコンポジションAPIには当てはまりません。

このステップでは、コンポーネントの1つをOptionsAPIの使用から新しいCompositionAPIにリファクタリングします。

テキストエディタで、AirportDetail.vueコンポーネントを開きます。 現在、このコンポーネントにミックスインがインポートされています。 そのミックスインは、いくつかの関数とデータプロパティを提供します。 ただし、Composition APIでは、コンポーネントがレンダリングする必要のあるものはすべてsetupメソッド内に存在します。 このメソッドをインポートする必要はありません。

ミックスインのインポートを削除し、mountedの下にsetupメソッドを追加します。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'

export default {
  components: { ... },
  methods: {
    getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }
  },
  mounted() { ... },
  setup() {
  
  }
}
</script>

setupメソッドを作成したら、新しいonMountedライフサイクルフックを追加して、これのリファクタリングを開始します。 onMounted関数は、1つの引数、通常は無名関数を受け入れます。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import { onMounted } from 'vue'

export default {
  components: { ... },
  methods: {
    getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }
  },
  mounted() { ... },
  setup() {
    onMounted(() => {
      
    })
  }
}
</script>

このコンポーネントがマウントされると、現在の空港オブジェクトをリアクティブデータプロパティに保存します。 変数または定数をリアクティブにするには、vueからインポートするref関数で値をラップする必要があります。 定数の名前は、コンポーネントのsetupセクションとtemplateセクションの参照の名前になります。 また、getAirportByCodemethodsから削除し、setup内の通常のJavaScript関数のように定義します。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import { onMounted, ref } from 'vue'

export default {
  components: { ... },
  mounted() { ... },
  setup() {
    function getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }
      
    onMounted(() => {
      const airport = ref(getAirportByCode())
    })
  }
}
</script>

その後、コンポーネントファイルから古いmountedおよびmethodsプロパティを削除できます。

現在ミックスインを使用していないため、setup関数内でgetAirportWithCodeを定義し、それを変数airportWithCodeに割り当てて、ビューで使用できるようにします。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import { onMounted, ref } from 'vue'

export default {
  components: {
    TwoColumnLayout
  },
  setup() {
    const airportWithCode = ref('')
    
    function getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }
      
    function getAirportWithCode(airport) {
      return `${airport.name} - ${airport.abbreviation}`
    }

      onMounted(() => {
        const airport = ref(getAirportByCode())
      })
    }
  }
</script>

Composition APIのリアクティブデータプロパティに関する非常に重要なことの1つは、refがオブジェクトを返すことです。 値にアクセスするには、その.valueプロパティにアクセスする必要があります。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import { onMounted, ref } from 'vue'

export default {
  components: {
    TwoColumnLayout
  },
  setup() {
    const airportWithCode = ref('')

    function getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === this.$route.params.code.toUpperCase())[0]
    }

    function getAirportWithCode(airport) {
      return `${airport.name} - ${airport.abbreviation}`
    }

    onMounted(() => {
      const airport = ref(getAirportByCode())
      airportWithCode.value = getAirportWithCode(airport.value)
    })
  }
}
</script>

これをCompositionAPIを使用して完全に変換する前に、2つのことを行う必要があります。 最初に変更する必要があるのは、getAirportByCode関数のthis.$routeです。 コンポジションAPIでは、this.$routethis.$routerでそれぞれルートまたはルーターにアクセスすることはできません。

ルートにアクセスするには、vue-routerパッケージからuseRouteをインポートします。 これをconstに保存して、アプリケーション全体で参照できるようにすることをお勧めします。

お気に入り-airports/src / views / AirportDetail.vue

...
<script>
import TwoColumnLayout from '@/layouts/TwoColumnLayout.vue'
import allAirports from '@/data/airports.js'
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'

export default {
  components: {
    TwoColumnLayout
  },
  setup() {
    const route = useRoute()
    const airportWithCode = ref('')

    function getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === route.params.code.toUpperCase())[0]
    }

    function getAirportWithCode(airport) {
      return `${airport.name} - ${airport.abbreviation}`
    }

    onMounted(() => {
      const airport = ref(getAirportByCode())
      airportWithCode.value = getAirportWithCode(airport.value)
    })
  }
}
</script>

それが完了したら、setup関数でオブジェクトを返します。 このオブジェクトで返されるプロパティは、templateで使用できます。

お気に入り-airports/src / views / AirportDetail.vue

...
  setup() {
    const route = useRoute()
    const airportWithCode = ref('')

    function getAirportByCode() {
      return allAirports.filter(airport => airport.abbreviation === route.params.code.toUpperCase())[0]
    }

    function getAirportWithCode(airport) {
      return `${airport.name} - ${airport.abbreviation}`
    }

    onMounted(() => {
      const airport = ref(getAirportByCode())
      airportWithCode.value = getAirportWithCode(airport.value)
    })
    
    return { airportWithCode }
  }
}
</script>

コードを保存し、ブラウザにlocalhost:8080/airport/cvgをリロードします。 コードをリファクタリングした後、レンダリングされる内容に変更はありません。 ただし、現在、CompositionAPIを利用しています。

結論

このチュートリアルでは、アプリケーションをDRYにするためのいくつかの戦略を試しました。 具体的には、複数のビューでレイアウトコンポーネントを再利用してから、モジュール化されたプロパティとメソッドをミックスインで再利用しました。 最後に、Vue3で導入された新しいCompositionAPIを使用するようにアプリをリファクタリングしました。 このAPIは、コンポーネントが作成される前にコンポーネントをセットアップする新しい方法であり、より多くの状況で機能するようになります。

MixinsまたはCompositionAPI について詳しく知りたい場合は、Vueの公式ドキュメントを確認することを強くお勧めします。 Vueのその他のチュートリアルについては、Vue.jsシリーズページを使用してWebサイトを開発する方法を確認してください。