uniapp-frontend について
uniapp-frontendは、uni-app、Vue 3、TypeScriptによるクロスプラットフォームアプリ開発向けのスキルです。ページ、テーマ、UIライブラリ、状態管理、プラットフォーム別ビルドのパターンとガイドを提供します。
主な機能
- 01ページとプロジェクト構成のガイド
- 02テーマとUIライブラリの統合
- 03Piniaによる状態管理パターン
- 04APIとナビゲーションの例
- 05プラットフォーム別ビルドのガイド
- 06再利用可能なページ・コンポーネントテンプレート
活用シーン
- 01uni-appのページ作成と登録
- 02アプリへの複数テーマの追加
- 03Piniaによるアプリ状態の管理
- 04H5またはWeChat Mini Program向けビルドの準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ enze00/ uniapp-frontend-skills --skill uniapp-frontendインストール後、Claude Code で/uniapp-frontendを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.gitignoreREADME.mdassets/page-template.vuereferences/theme-guide.mdui-libraries.mdpage-patterns.md詳細
uni-app フロントエンド開発
uni-app、Vue 3、TypeScript を使用してクロスプラットフォームアプリを構築するための包括的なガイドです。
クイックスタート
新しいページを作成する
# Create page directory
mkdir -p src/pages/newpage
# Create page files
touch src/pages/newpage/index.vue
pages.json にページを登録する
{
"pages": [
{
"path": "pages/newpage/index",
"style": {
"navigationBarTitleText": "Page Title"
}
}
]
}
基本的なページテンプレート
完全なページテンプレートについては、assets/page-template.vue を参照してください。
プロジェクト構成
標準的な uni-app CLI プロジェクトの構成です。
src/
├── pages/ # Page components (one per directory)
├── components/ # Shared/reusable components
├── store/ # Pinia state management
├── api/ # API interface definitions
├── utils/ # Utility functions
├── types/ # TypeScript type definitions
├── styles/ # Global styles
│ ├── theme.scss # Theme variables
│ └── common.scss # Common styles
├── static/ # Static assets (images, icons)
├── App.vue # App root component
├── main.ts # App entry point
├── pages.json # Page and tabBar configuration
└── uni.scss # uni-app built-in variables
UI ライブラリの統合
uView Plus
インストール:
npm install uview-plus
設定:
App.vue - スタイルをインポート:
<style lang="scss">
@import "uview-plus/index.scss";
@import "@/styles/common.scss";
</style>
main.ts - プラグインを登録:
import uviewPlus from "uview-plus";
app.use(uviewPlus);
vite.config.ts - SCSS をグローバルに設定:
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/theme.scss";@import "uview-plus/theme.scss";`,
api: "modern-compiler",
},
},
}
その他の UI ライブラリ
uni-ui(公式):
npm install @dcloudio/uni-ui
TuniaoUI(Tuniao):
npm install @tuniao/tnui-vue3-uniapp
統合ガイドについては、references/ui-libraries.md を参照してください。
テーマシステムの設計
複数のロールやブランドに対応するアプリ向けに、柔軟なテーマ設定を実装します。
基本的なテーマ設定
src/styles/theme.scss:
// Theme colors
$theme-primary: #1890ff;
$theme-success: #52c41a;
$theme-warning: #faad14;
$theme-error: #f5222d;
// Neutral colors
$color-text-primary: #333333;
$color-text-regular: #666666;
$color-text-secondary: #999999;
$color-bg-page: #f5f5f5;
$color-bg-card: #ffffff;
// Spacing scale
$spacing-xs: 8rpx;
$spacing-sm: 16rpx;
$spacing-md: 24rpx;
$spacing-lg: 32rpx;
$spacing-xl: 48rpx;
// Typography
$font-size-xs: 20rpx;
$font-size-sm: 24rpx;
$font-size-base: 28rpx;
$font-size-lg: 32rpx;
$font-size-xl: 36rpx;
// Border radius
$border-radius-sm: 4rpx;
$border-radius-md: 8rpx;
$border-radius-lg: 16rpx;
$border-radius-circle: 50%;
vite.config.ts - グローバルに読み込む:
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/theme.scss";`,
api: "modern-compiler",
},
},
}
複数テーマの実装
複数のテーマが必要なアプリ(例:ユーザー/管理者、異なるブランド)の場合:
オプション 1:環境ごとのテーマ変数
// src/styles/theme.scss
// Define different theme color sets
$theme-user-primary: #1890ff;
$theme-admin-primary: #0050b3;
// Set active theme
$theme-primary: $theme-user-primary; // Change based on build/env
オプション 2:テーマの動的な切り替え
// store/theme.ts
import { defineStore } from 'pinia';
export const useThemeStore = defineStore('theme', {
state: () => ({
currentTheme: 'default',
}),
getters: {
themeColors() {
const themes = {
default: { primary: '#1890ff' },
dark: { primary: '#0050b3' },
};
return themes[this.currentTheme];
},
},
});
テーマ設定のパターン全般については、references/theme-guide.md を参照してください。
ビルドコマンド
# WeChat Mini Program
npm run dev:mp-weixin # Development
npm run build:mp-weixin # Production
# H5
npm run dev:h5 # Development
npm run build:h5 # Production
# Other platforms
npm run dev:mp-alipay # Alipay Mini Program
npm run dev:mp-baidu # Baidu Mini Program
npm run dev:mp-toutiao # Toutiao Mini Program
よく使われるパターン
データ取得パターン
<script setup lang="ts">
import { ref, onMounted } from "vue";
interface Item {
id: number;
title: string;
}
const items = ref<Item[]>([]);
const loading = ref(false);
const error = ref<string | null>(null);
onMounted(() => {
loadData();
});
const loadData = async () => {
loading.value = true;
error.value = null;
try {
const data = await api.getItems();
items.value = data;
} catch (err) {
error.value = "Failed to load data";
uni.showToast({ title: error.value, icon: "none" });
} finally {
loading.value = false;
}
};
</script>
ナビゲーションパターン
// Navigate to page (adds to history stack)
uni.navigateTo({ url: "/pages/detail/index" });
// Navigate with parameters
uni.navigateTo({ url: `/pages/detail/index?id=${id}&type=parcel` });
// Redirect (replaces current page, no back button)
uni.redirectTo({ url: "/pages/login/index" });
// Switch to tabBar page
uni.switchTab({ url: "/pages/home/index" });
// Navigate back
uni.navigateBack();
// Launch another mini program
uni.navigateToMiniProgram({
appId: "xxxxx",
path: "pages/index/index",
});
ユーザーへのフィードバック
トースト:
uni.showToast({
title: "Success",
icon: "success",
duration: 2000,
});
uni.showToast({
title: "Error message",
icon: "none",
});
// Loading toast
uni.showLoading({ title: "Loading..." });
uni.hideLoading();
モーダル:
uni.showModal({
title: "Confirm",
content: "Are you sure?",
success: (res) => {
if (res.confirm) {
// User clicked confirm
}
},
});
アクションシート:
uni.showActionSheet({
itemList: ["Option 1", "Option 2", "Option 3"],
success: (res) => {
console.log("Selected:", res.tapIndex);
},
});
ライフサイクルフック
<script setup lang="ts">
import {
onLaunch,
onShow,
onHide,
onUnload,
} from "@dcloudio/uni-app";
import { onLoad, onReady, onReachBottom, onPullDownRefresh } from "@dcloudio/uni-app";
// App-level hooks (use in App.vue)
onLaunch(() => {
console.log("App launched");
});
onShow(() => {
console.log("App shown");
});
// Page-level hooks (use in pages)
onLoad((options) => {
console.log("Page loaded with params:", options);
});
onReady(() => {
console.log("Page ready");
});
onReachBottom(() => {
console.log("Reached bottom - load more");
});
onPullDownRefresh(() => {
console.log("Pull down refresh");
// Stop loading after data fetch
uni.stopPullDownRefresh();
});
</script>
プラットフォームの検出
// Get platform info
const systemInfo = uni.getSystemInfoSync();
console.log("Platform:", systemInfo.platform); // ios, android, devtools
console.log("System:", systemInfo.system); // iOS 14.5, Android 10
// Conditional code based on platform
// #ifdef H5
console.log("Running on H5");
// #endif
// #ifdef MP-WEIXIN
console.log("Running on WeChat Mini Program");
// #endif
// #ifdef MP-ALIPAY
console.log("Running on Alipay Mini Program");
// #endif
Pinia による状態管理
ストアの定義:
// src/store/user.ts
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
token: '',
}),
getters: {
isLoggedIn: (state) => !!state.token,
},
actions: {
async login(credentials) {
const data = await api.login(credentials);
this.token = data.token;
this.userInfo = data.user;
},
logout() {
this.token = '';
this.userInfo = null;
},
},
});
コンポーネントでの使用:
<script setup lang="ts">
import { useUserStore } from "@/store/user";
const userStore = useUserStore();
// Access state
console.log(userStore.userInfo);
// Call actions
await userStore.login({ username, password });
// Use getters
if (userStore.isLoggedIn) {
// ...
}
</script>
API の統合
API モジュール:
// src/api/index.ts
const BASE_URL = "https://api.example.com";
export const api = {
// GET request
async getItems() {
const res = await uni.request({
url: `${BASE_URL}/items`,
method: "GET",
});
return res.data;
},
// POST request
async createItem(data: any) {
const res = await uni.request({
url: `${BASE_URL}/items`,
method: "POST",
data,
});
return res.data;
},
};
インターセプターを使用する場合:
// src/utils/request.ts
let token = "";
export const request = (options: UniApp.RequestOptions) => {
// Add token
if (token) {
options.header = {
...options.header,
Authorization: `Bearer ${token}`,
};
}
return uni.request(options);
};
// Set token after login
export const setToken = (newToken: string) => {
token = newToken;
};
トラブルシューティング
SCSS 変数が見つからない
エラー: Undefined variable $spacing-md
解決方法:
vite.config.tsにadditionalDataの設定があることを確認します- テーマファイルのパスが正しいことを確認します
- 設定を変更した後、開発サーバーを再起動します
コンポーネントがレンダリングされない
確認事項:
- コンポーネントが
pages.jsonに登録されていること - インポートパスが正しいこと(
@/エイリアスを使用) - Vue コンポーネント名が PascalCase であること
ビルドエラー
一般的な解決方法:
- キャッシュをクリアします:
rm -rf node_modules dist && npm install - Node.js のバージョンを確認します(LTS を使用)
- 依存関係に互換性があることを確認します
プラットフォーム固有の問題
WeChat ミニプログラム:
manifest.jsonの appid が正しいことを確認します- ミニプログラム管理コンソールでドメインの許可リストを確認します
- WeChat DevTools でテストします
H5:
- 複数のブラウザーでテストします
- CORS の設定を確認します
- API エンドポイントが HTTPS に対応していることを確認します
リソース
references/theme-guide.md
複数テーマのパターン、色彩理論、実装方法を含む、テーマシステム設計の完全ガイドです。
references/ui-libraries.md
uView Plus、uni-ui、TuniaoUI など、人気の UI ライブラリの統合ガイドです。
references/page-patterns.md
再利用可能なページパターン:一覧ページ、詳細ページ、フォーム、検索/フィルター、空の状態など。
references/platform-specific.md
WeChat、Alipay、H5 など、各プラットフォーム固有の考慮事項とベストプラクティスです。
assets/page-template.vue
カスタマイズしてすぐに使える、Vue 3 と TypeScript による最小限のページテンプレートです。
assets/component-templates/
一般的なコンポーネントテンプレート(カード、ボタングループ、リスト項目など)。
ベストプラクティス
- TypeScript を使用する - コンパイル時にエラーを検出します
- コンポーネントを組み合わせる - コンポーネントは小さく、役割を明確に保ちます
- 状態管理 - 複雑な状態管理には Pinia を使用します
- エラー処理 - API エラーは常に適切に処理します
- 読み込み状態 - 非同期処理中は読み込みインジケーターを表示します
- レスポンシブデザイン - 複数の画面サイズでテストします
- パフォーマンス - 画像や長いリストは遅延読み込みします
- アクセシビリティ - セマンティック HTML と ARIA ラベルを使用します
- コードの整理 - 一貫性のあるファイル構成に従います
- バージョン管理 - 意味のあるメッセージを付けて、こまめにコミットします