vue 3.0でスマホアプリを開発中です。
ユーザー認証を行い、権限ごとにFooterメニューの中身を変更したいと考えました。
テスト駆動で行いたいため、
ユーザーと権限の型をインターフェースで定義しています。
また、Footerメニューと権限の選択などはvueのInject機能で実装します。
アプリ構造
App.vue
main.ts
\views
FooterMenu.vue(フッターメニュー)
LoginMenu.vue(ログインさせたり権限選択を変えたり)
Contents.vue(表示するコンテンツ)
\stores
UserStore.ts(共有するProvideInjectのもの)
データは
IUser(Name:string、Role:IRole)
IRole(RoleName:string、isManager:boolean)
という形でUserの中にRoleを持たせています。
使う時は、
export class AppUser implements IUser {....}
export class AppRole implements IRole {....}
storeKeyを利用して
userStore.ts
import { InjectionKey,inject } from 'vue';
import { IUser, IRole } from '../interfaces/IUser';
export const UserStoreKey: InjectionKey<IUser> = Symbol("User");
export function useUserStore() {
const store = inject(UserStoreKey);
if(!store) {
throw new Error('store not found');
}
return store;
}
こういうのを用意。InjectionKeyで検索すれば詳しく解説している人がいます!
App.vue
<script setup lang="ts">
import { onMounted, provide, reactive } from 'vue'
import { UserStoreKey } from './stores/UserStore';
const expRole = new AppRole();
const expUser = reactive(new AppUser());
expUser.Role = expRole;
provide ( UserStoreKey, expUser);
</script>
App.vueにてInjectionするのですが、この時に、reactive()を付けます。
付けないとLoginMenu.vueで変更したものがFooter.vueに反映されなかったりします。
また、refで各値を作っても良さそうですが、入れ子になっていると上手く動かなかったりします。
使い方の注意は
Footer.vue
<script setup lang="ts">
import { useUserStore } from '../stores/UserStore';
const currentRole = useUserStore();
const { Role } = toRefs(currentRole);
</script>
toRefsしないとFooter.vueでリアクティブになりません。