データ辞書ドキュメント - 辞書管理とコンポーネント使用
概要
このドキュメントは、VJSP Vue3フレームワークのデータ辞書管理システムについて詳しく説明します。データ辞書は統一された列挙値管理ソリューションを提供し、ステータスコード、タイプ識別子などのデータの集中管理と動的ローディングをサポートし、データの一貫性と保守性を確保します。
辞書アーキテクチャ
コア機能
- 統一管理: すべての列挙データを集中管理し、ハードコーディングを回避
- 動的ローディング: ランタイムでの辞書データの動的ローディングをサポート
- インテリジェントキャッシュ: 自動キャッシュメカニズムによるパフォーマンス向上
- タイプセーフ: 完全なTypeScriptタイプ定義サポート
- エラーハンドリング: 包括的なエラーハンドリングとリトライメカニズム
技術スタック
- Pinia状態管理: 辞書データの状態管理とキャッシュ
- 非同期ローディング: 辞書データの非同期取得と更新をサポート
- コンポーネント統合: Element Plusコンポーネントライブラリとの深い統合
辞書管理メカニズム
辞書データストレージ
辞書データは集中ストレージ管理を使用:
- メモリキャッシュ: 辞書データをメモリにキャッシュして高速アクセス
- 自動期限切れ: キャッシュデータは自動的に期限切れになり、データの鮮度を確保
- 強制更新: 辞書データの手動強制更新をサポート
辞書ローディングプロセス
- アプリケーション起動: キャッシュの有効性を確認
- データローディング: バックエンドAPIから辞書データを取得
- キャッシュ更新: メモリキャッシュとタイムスタンプを更新
- エラーハンドリング: ネットワークエラーとリトライロジックを処理
キャッシュ戦略
フレームワークはインテリジェントなキャッシュ戦略を実装:
- キャッシュ期間: 5分間の自動期限切れ
- リトライメカニズム: 最大3回のリトライと指数バックオフ遅延
- 同時実行制御: 重複リクエストを防止してリソースの浪費を回避
辞書ユーティリティ関数
基本辞書アクセス
フレームワークはローディングとエラーを自動的に処理する安全な辞書アクセス関数を提供:
getSafeDictLabel: 安全に辞書ラベルを取得getSafeDictValue: 安全に辞書値を取得getSafeDictOptions: 安全に辞書オプションリストを取得batchGetDictLabels: バッチで辞書ラベルを取得hasDictType: 辞書タイプの存在を確認
辞書状態管理
辞書ストアモジュールを通じて辞書データを管理:
getDictData: 辞書データを取得(キャッシュを自動的に処理)getDictByType: タイプ別に辞書アイテムを取得getDictLabel: 辞書ラベルを取得getDictValue: 辞書値を取得refreshDictData: 辞書データを更新clearDictData: 辞書キャッシュをクリア
辞書コンポーネント使用
コンポーネントコレクション
フレームワークは完全な辞書コンポーネントコレクションを提供:
- DictSelect: 辞書セレクター
- DictTag: 辞書タグ表示
- DictRadio: 辞書ラジオコンポーネント
- DictCheckbox: 辞書チェックボックスコンポーネント
- DictSwitch: 辞書スイッチコンポーネント
- DictCascader: 辞書カスケードセレクター
コンポーネント機能
すべての辞書コンポーネントは以下の機能を持ちます:
- 自動ローディング: 対応する辞書タイプデータを自動的にロード
- エラーハンドリング: 辞書データのローディング失敗を処理
- タイプセーフ: 完全なTypeScriptタイプサポート
- スタイル一貫性: Element Plusコンポーネントスタイルとの一貫性
ビジネスモジュール開発ガイド(Productモジュール)
1. 辞書タイプの定義
辞書管理システムで製品関連の辞書タイプを定義:
product_status: 製品ステータス辞書product_category: 製品カテゴリ辞書product_type: 製品タイプ辞書
2. 製品管理ページの作成
src/views/modules/product/list.vue
vue
<template>
<div class="product-list">
<!-- 検索フォーム -->
<el-form :model="queryParams" inline>
<el-form-item label="製品ステータス">
<DictSelect
v-model="queryParams.status"
dict-type="product_status"
placeholder="製品ステータスを選択してください"
clearable
/>
</el-form-item>
<el-form-item label="製品カテゴリ">
<DictSelect
v-model="queryParams.category"
dict-type="product_category"
placeholder="製品カテゴリを選択してください"
clearable
/>
</el-form-item>
<el-button type="primary" @click="handleQuery">検索</el-button>
<el-button @click="resetQuery">リセット</el-button>
</el-form>
<!-- データテーブル -->
<el-table :data="productList" v-loading="loading">
<el-table-column prop="productName" label="製品名" />
<el-table-column prop="productCode" label="製品コード" />
<el-table-column prop="status" label="製品ステータス">
<template #default="{ row }">
<DictTag :value="row.status" dict-type="product_status" />
</template>
</el-table-column>
<el-table-column prop="category" label="製品カテゴリ">
<template #default="{ row }">
<DictTag :value="row.category" dict-type="product_category" />
</template>
</el-table-column>
<el-table-column prop="type" label="製品タイプ">
<template #default="{ row }">
<DictTag :value="row.type" dict-type="product_type" />
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button size="small" @click="handleEdit(row)">編集</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">削除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useProductApi } from '@/api/modules/product'
const queryParams = ref({
status: '',
category: '',
productName: '',
})
const productList = ref([])
const loading = ref(false)
const loadProductList = async () => {
loading.value = true
try {
const response = await useProductApi().getList(queryParams.value)
productList.value = response.data.list
} finally {
loading.value = false
}
}
const handleQuery = () => {
loadProductList()
}
const resetQuery = () => {
queryParams.value = {
status: '',
category: '',
productName: '',
}
loadProductList()
}
onMounted(() => {
loadProductList()
})
</script>3. 製品作成/編集フォーム
src/views/modules/product/form.vue
vue
<template>
<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px">
<el-form-item label="製品名" prop="productName">
<el-input v-model="formData.productName" placeholder="製品名を入力してください" />
</el-form-item>
<el-form-item label="製品ステータス" prop="status">
<DictRadio v-model="formData.status" dict-type="product_status" :options="statusOptions" />
</el-form-item>
<el-form-item label="製品カテゴリ" prop="category">
<DictSelect
v-model="formData.category"
dict-type="product_category"
placeholder="製品カテゴリを選択してください"
/>
</el-form-item>
<el-form-item label="製品タイプ" prop="type">
<DictCheckbox v-model="formData.type" dict-type="product_type" :options="typeOptions" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit">送信</el-button>
<el-button @click="handleCancel">キャンセル</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const formRef = ref()
const formData = reactive({
productName: '',
status: '',
category: '',
type: [],
})
const rules = {
productName: [{ required: true, message: '製品名は必須です', trigger: 'blur' }],
status: [{ required: true, message: '製品ステータスは必須です', trigger: 'change' }],
}
const handleSubmit = async () => {
try {
await formRef.value.validate()
// フォームデータを送信
console.log('フォーム送信:', formData)
router.push('/product/list')
} catch (error) {
console.error('フォーム検証失敗:', error)
}
}
const handleCancel = () => {
router.push('/product/list')
}
</script>高度な辞書使用
カスタム辞書コンポーネント
特定のビジネスニーズに合わせてカスタム辞書コンポーネントを作成:
vue
<!-- src/components/DictColorTag.vue -->
<template>
<el-tag :color="getTagColor(value)" effect="dark">
{{ getDictLabel(value, dictType) }}
</el-tag>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useDictStore } from '@/stores/dict'
interface Props {
value: string | number
dictType: string
}
const props = defineProps<Props>()
const dictStore = useDictStore()
const getTagColor = (value: string | number) => {
const colorMap = {
active: '#67C23A',
inactive: '#909399',
pending: '#E6A23C',
rejected: '#F56C6C',
}
return colorMap[value] || '#909399'
}
const getDictLabel = computed(() => {
return (value: string | number, type: string) => {
return dictStore.getDictLabel(type, value) || value
}
})
</script>辞書データ検証
辞書ベースのフォーム検証を実装:
typescript
// src/utils/validation.ts
import { useDictStore } from '@/stores/dict'
export const createDictValidator = (dictType: string) => {
return (value: any) => {
const dictStore = useDictStore()
const dictOptions = dictStore.getDictByType(dictType)
const validValues = dictOptions.map(item => item.value)
if (!validValues.includes(value)) {
return new Error(`辞書タイプの無効な値: ${dictType}`)
}
return true
}
}
// フォーム検証での使用
const rules = {
status: [
{ required: true, message: 'ステータスは必須です' },
{ validator: createDictValidator('product_status'), trigger: 'change' },
],
}パフォーマンス最適化
遅延ローディング辞書
オンデマンドで辞書をロードして初期ロードパフォーマンスを向上:
typescript
// src/hooks/useLazyDict.ts
import { ref } from 'vue'
import { useDictStore } from '@/stores/dict'
export function useLazyDict(dictType: string) {
const dictStore = useDictStore()
const loading = ref(false)
const loaded = ref(false)
const loadDict = async () => {
if (loaded.value || dictStore.hasDictType(dictType)) {
return
}
loading.value = true
try {
await dictStore.loadDictData(dictType)
loaded.value = true
} finally {
loading.value = false
}
}
return {
loading,
loaded,
loadDict,
}
}辞書事前ローディング
アプリケーション初期化時に一般的に使用される辞書を事前ロード:
typescript
// src/utils/dictPreloader.ts
import { useDictStore } from '@/stores/dict'
export const preloadCommonDicts = async () => {
const dictStore = useDictStore()
const commonDictTypes = ['product_status', 'product_category', 'user_status', 'order_status']
await Promise.allSettled(commonDictTypes.map(type => dictStore.loadDictData(type)))
}エラーハンドリングとデバッグ
辞書エラーモニタリング
辞書ローディングエラーを監視し、フォールバックメカニズムを提供:
typescript
// src/utils/dictErrorHandler.ts
export class DictErrorHandler {
static handleLoadError(error: Error, dictType: string) {
console.error(`辞書のロードに失敗しました: ${dictType}`, error)
// エラートラッキングサービスに送信
if (import.meta.env.PROD) {
// 監視サービスに送信
}
// フォールバックデータを提供
return this.getFallbackDict(dictType)
}
static getFallbackDict(dictType: string) {
const fallbackDicts = {
product_status: [
{ label: '有効', value: 'active' },
{ label: '無効', value: 'inactive' },
],
// その他のフォールバック辞書を追加
}
return fallbackDicts[dictType] || []
}
}デバッグツール
辞書開発用のデバッグツールを追加:
typescript
// src/utils/dictDebug.ts
export const dictDebug = {
logDictState: (dictType: string) => {
const dictStore = useDictStore()
console.log(`辞書 [${dictType}]:`, dictStore.getDictByType(dictType))
},
monitorDictChanges: (dictType: string) => {
const dictStore = useDictStore()
watch(
() => dictStore.getDictByType(dictType),
(newDict, oldDict) => {
console.log(`辞書 [${dictType}] が変更されました:`, { old: oldDict, new: newDict })
}
)
},
}この包括的な辞書管理システムは、VJSP Vue3フレームワークで列挙データを処理するための堅牢な基盤を提供し、すべてのビジネスモジュールでデータの一貫性、タイプセーフ、最適なパフォーマンスを確保します。
