ionic-vue について
Vue で Ionic アプリを開発するエージェント向けのスキルガイドです。プロジェクト設定を確認し、既存のコードスタイルに合わせてコンポーネント、ナビゲーション、ライフサイクル、コンポーザブル、プラットフォーム検出を案内します。
主な機能
- 01依存関係、プラットフォーム、構成の検出
- 02ルーティングとタブナビゲーションの設定
- 03Ionic ページライフサイクルフックの適用
- 04Vue コンポーザブルとコンポーネントの利用
- 05プラットフォーム検出とビルド手順の案内
活用シーン
- 01既存 Ionic Vue プロジェクトへのページ追加
- 02画面遷移やライフサイクル動作の問題調査
- 03タブナビゲーションとプラットフォーム別処理の実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ capawesome-team/ skills --skill ionic-vueインストール後、Claude Code で/ionic-vueを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/components.mdcomposables.mdlifecycle.mdnavigation.md詳細
Ionic Vue
Vue で Ionic アプリを開発するための、プロジェクト構成、コンポーネント、ナビゲーション、ライフサイクルフック、コンポーザブル、Vue 固有のパターンです。
前提条件
- Ionic Framework 7 または 8 と
@ionic/vue。 - Vue 3。
- Node.js と npm がインストールされていること。
- iOS の場合:Xcode がインストールされていること。
- Android の場合:Android Studio がインストールされていること。
エージェントの動作
- 質問する前に自動検出します。 プロジェクト内の
package.jsonの依存関係(@ionic/vue、vue、@capacitor/core)、プラットフォーム(android/、ios/)、ビルドツール(vite.config.ts)、TypeScript の使用状況を確認します。検出できない場合にのみユーザーに質問します。 - 手順を追って案内します。 一度に一つずつ、ユーザーを手順に沿って案内します。関連のない複数の質問を一度に提示してはいけません。
- プロジェクトに合わせます。 プロジェクトが
<script setup>(Composition API)を使っているか Options API を使っているかを検出し、既存のスタイルに合ったコードを生成します。プロジェクトで異なるパターンが使われていない限り、新しいファイルでは<script setup lang="ts">をデフォルトとします。
手順
ステップ 1:プロジェクトを分析する
プロジェクトファイルを読み取り、以下を自動検出します。
- Ionic のバージョン:
package.jsonから@ionic/vueのバージョンを読み取ります。 - Vue のバージョン:
package.jsonからvueのバージョンを読み取ります。 - Capacitor のバージョン:
package.jsonから@capacitor/coreのバージョンを読み取ります(存在する場合)。 - TypeScript:
tsconfig.jsonが存在するか、および.vueファイルで<script setup lang="ts">が使われているかを確認します。 - プラットフォーム:存在するディレクトリ(
android/、ios/)を確認します。 - ルーター設定:ルーターファイルの場所を特定します(通常は
src/router/index.ts)。 - プロジェクトテンプレート:ルーター設定と
App.vueを調べ、プロジェクトがタブ、サイドメニュー、または空のテンプレートを使っているか判断します。
ステップ 2:プロジェクト構成
標準的な Ionic Vue プロジェクトは、次の構成に従います。
project-root/
├── android/ # Android native project (generated by Capacitor)
├── ios/ # iOS native project (generated by Capacitor)
├── public/
├── src/
│ ├── components/ # Reusable Vue components
│ ├── composables/ # Custom composables
│ ├── router/
│ │ └── index.ts # Vue Router configuration (uses @ionic/vue-router)
│ ├── theme/
│ │ └── variables.css # Ionic CSS custom properties
│ ├── views/ # Page components (routed views)
│ ├── App.vue # Root component (contains IonApp + IonRouterOutlet)
│ └── main.ts # Entry point (installs IonicVue plugin)
├── capacitor.config.ts # Capacitor configuration
├── package.json
├── tsconfig.json
└── vite.config.ts
プロジェクトがこの構成に従っていない場合は、プロジェクトの実際のディレクトリ構成に合わせてすべての案内を調整します。ユーザーから明示的に依頼されない限り、プロジェクトの構成を変更してはいけません。
ステップ 3:アプリのエントリーポイントとルートコンポーネント
エントリーポイントの src/main.ts では、IonicVue プラグインをインストールしてアプリをマウントします。
import { createApp } from 'vue';
import { IonicVue } from '@ionic/vue';
import App from './App.vue';
import router from './router';
/* Ionic CSS */
import '@ionic/vue/css/core.css';
import '@ionic/vue/css/normalize.css';
import '@ionic/vue/css/structure.css';
import '@ionic/vue/css/typography.css';
import '@ionic/vue/css/padding.css';
import '@ionic/vue/css/float-elements.css';
import '@ionic/vue/css/text-alignment.css';
import '@ionic/vue/css/text-transformation.css';
import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';
/* Theme */
import './theme/variables.css';
const app = createApp(App).use(IonicVue).use(router);
router.isReady().then(() => {
app.mount('#app');
});
ルートの App.vue には IonApp と IonRouterOutlet を配置します。
<template>
<ion-app>
<ion-router-outlet />
</ion-app>
</template>
<script setup lang="ts">
import { IonApp, IonRouterOutlet } from '@ionic/vue';
</script>
ステップ 4:コンポーネントと IonPage
詳細なコンポーネントのパターンについては、references/components.md を読みます。
主なルール:
- すべての Ionic コンポーネントを
@ionic/vueからインポートします。例:import { IonButton, IonContent, IonPage } from '@ionic/vue'。 - ルーティングされるすべてのページでは、ルートのテンプレート要素に
IonPageを使います。使わないとページ遷移が正しく動作せず、Ionic のライフサイクルフックも実行されません。 - Web Component のメソッドには
$el経由でアクセスします。例:contentRef.value.$el.scrollToBottom(300)。 - アイコンは
ionicons/iconsから SVG 参照としてインポートします。アイコン名を文字列として渡してはいけません。 - Ionic のフォームコンポーネント(
IonInput、IonToggle、IonSelect、IonCheckbox、IonRange)ではv-modelを使います。 - テンプレートでは Ionic のイベント名にケバブケースを使います。例:
@ion-change、@ion-infinite。
ステップ 5:ナビゲーションとルーティング
詳細なルーティングのパターンについては、references/navigation.md を読みます。
主な原則:
createRouterはvue-routerではなく@ionic/vue-routerからインポートします。Ionic 版は Vue Router をラップし、ページ遷移を有効にします。- 宣言的なナビゲーション:Ionic コンポーネントの
router-link属性を使い、必要に応じてrouter-directionとrouter-animationを指定します。 - プログラムによるナビゲーション:Ionic 固有の遷移には
useIonRouterコンポーザブルを使います。標準的なナビゲーションにはvue-routerのuseRouterを使います。 component: () => import('@/views/DetailPage.vue')のようにして、ルートを遅延読み込みします。- タブのルーティング:
IonTabsとIonRouterOutletを使い、ネストされたルートを設定します。各タブは独自のナビゲーションスタックを保持します。 - タブ間をルートで移動してはいけません。タブを切り替えるのはタブバーのボタンだけにします。タブ間で共有するビューには
IonModalを使います。
ステップ 6:ライフサイクルフック
ライフサイクルのパターンについて詳しくは、references/lifecycle.md をお読みください。
主な原則:
IonRouterOutletはページを DOM に保持します。Vue のonMountedはページごとに一度だけ実行され、訪問のたびには実行されません。- ページを訪問するたびにロジックを実行するには、Ionic のライフサイクルフックを使用します。
onIonViewWillEnter— ページが表示されるたびにデータを更新します。onIonViewDidEnter— ページ遷移の完了後にアニメーションを開始するか、入力欄にフォーカスします。onIonViewWillLeave— 状態を保存するか、購読を解除します。onIonViewDidLeave— 画面外のリソースをクリーンアップします。
- Ionic のライフサイクルフックを使用するには、ルート要素に
IonPageが必要です。 - ライフサイクルフックを受け取るのはルーターにマッピングされたコンポーネントのみです。子コンポーネントには適用されません。
ステップ 7:コンポーザブルとユーティリティ
コンポーザブルの詳細については、references/composables.md をお読みください。
@ionic/vue で利用できるコンポーザブルとユーティリティ:
| 関数 | 用途 |
|---|---|
useIonRouter() | 遷移を制御するプログラムによるナビゲーション |
useBackButton(priority, handler) | Android のハードウェア戻るボタンを処理します |
useKeyboard() | キーボードの表示状態と高さをリアクティブに取得します |
onIonViewWillEnter(cb) | ライフサイクル:ページが表示される直前 |
onIonViewDidEnter(cb) | ライフサイクル:ページが完全に表示された後 |
onIonViewWillLeave(cb) | ライフサイクル:ページが非表示になる直前 |
onIonViewDidLeave(cb) | ライフサイクル:ページが完全に非表示になった後 |
isPlatform(name) | 現在のプラットフォーム(ios、android、hybrid など)を確認します |
getPlatforms() | 一致するすべてのプラットフォーム識別子の配列を取得します |
ステップ 8:プラットフォームの検出
@ionic/vue の isPlatform を使用して、プラットフォーム固有のロジックを条件付きで実行します。
<script setup lang="ts">
import { isPlatform } from '@ionic/vue';
const isIOS = isPlatform('ios');
const isAndroid = isPlatform('android');
const isNative = isPlatform('hybrid');
const isMobileWeb = isPlatform('mobileweb');
</script>
<template>
<div>
<p v-if="isNative">Running as a native app</p>
<p v-else>Running in a browser</p>
</div>
</template>
対応する識別子:android、capacitor、cordova、desktop、electron、hybrid、ios、ipad、iphone、mobile、mobileweb、phablet、pwa、tablet。
ステップ 9:ビルドと実行
変更を実装した後:
npm run build
npx cap sync
npx cap run android
npx cap run ios
ライブリロードを使用した開発の場合:
ionic serve
ネイティブのライブリロードの場合:
ionic cap run android --livereload --external
ionic cap run ios --livereload --external
エラー処理
Failed to resolve component: ion-*:Ionic コンポーネントがインポートされていません。<script>セクションで@ionic/vueから不足しているインポートを追加します(例:import { IonButton } from '@ionic/vue')。- ページ遷移が機能しない:ページコンポーネントのルートテンプレート要素に
IonPageが使用されていることを確認します。IonPageがないと、遷移とライフサイクルフックは警告なしに失敗します。 - Ionic のライフサイクルフックが実行されない:
IonPageがルート要素であり、コンポーネントがルーター設定のルートに直接マッピングされていることを確認します。ライフサイクルフックは子コンポーネントでは実行されません。 Method on component is not a function:$elを介して基盤となる Web Component にアクセスします。たとえば、ref.value.scrollToBottom()ではなく、ref.value.$el.scrollToBottom()を使用します。- Slot 属性の非推奨警告:Ionic は Web Component のスロットを使用しますが、リンターはこれを Vue 2 の非推奨スロットと誤認します。ESLint ルールを無効にします:
'vue/no-deprecated-slot-attribute': 'off'。 - イベントリスナーが実行されない:テンプレート(
ion-modal-did-present)とaddEventListenerの呼び出しの両方で、ケバブケースのイベント名を使用します。キャメルケースは使用しないでください。 useIonRouterまたはuseBackButtonが失敗する:これらのコンポーザブルは内部で Vue のinject()を使用するため、単独の関数やコールバックではなく、setup()または<script setup>内で呼び出す必要があります。- タブナビゲーションで状態が失われる:各タブは独自のスタックを保持します。非線形(タブベース)のルーティングで
router.go()を使用しないでください。代わりにuseIonRouter().push()またはrouter-linkを使用します。 - Vue の
onMountedが一度しか実行されない:IonRouterOutletはページを DOM にキャッシュします。ページが表示されるたびに実行する必要があるロジックには、onMountedの代わりにonIonViewWillEnterを使用します。 - コンテンツがタブバーまたはヘッダーに重なる:ページコンポーネントのルート要素に
IonPageがありません。IonPageは適切な Flexbox レイアウトを設定します。
関連スキル
ionic-app-development— Ionic 開発全般のガイダンス:コンポーネント、テーマ設定、CLI の使用方法。ionic-app-creation— Ionic アプリをゼロから新規作成します。capacitor-vue— Ionic Framework を使わない、Capacitor 固有の Vue パターン(プラグイン、フック、サービス)。ionic-app-upgrades— Ionic Framework を新しいバージョンにアップグレードします。