vue3.0 decorators 修飾器 使用
阿新 • • 發佈:2020-12-12
Vue Pandora Decorators
- npm i vue-pandora-decorators --save
- yarn add vue-pandora-decorators
本外掛基於 VUE 3.0 開發
- vuex 修飾器及 Composition API 支援
- 面向物件 @Component 支援
- 提供 @Mixin 繼承
- 本外掛主要是用 Proxy 代理模式 代理 Vue Context
基礎使用
Component 修飾器使用 使用
- components/test2.vue
<template> <div>Test2 ...</div> <div>{{aaa}}</div> <div>{{name}}</div> <div>{{object}}</div> <div>{{test}}</div> <div>{{computed}}</div> <el-button @click="()=>edit()">修改</el-button> </template> <script lang="ts"> import { ToRefs, watch } from 'vue'; import { Component, dynamic, Prop, PureComponent, Reactived, computed } from 'vue-pandora-decorator'; export interface Props { aaa: number; } export interface State { name: number; object: any; } // 這裡可以不定義 Props 和 State 預設 any @Component export default class Test2 extends PureComponent<Props, State> implements Reactived<State> { @dynamic public name: number; @dynamic public object: any; public test: boolean; @Prop public aaa!: number; @computed public get computed() { return `${(new Date).getTime()} ${this.aaa} ${JSON.stringify(this.object)}`; } constructor(props: any, ctx: any){ super(props, ctx); this.name = 111; this.object = {}; this.test = true; // // 下面兩種等同 // console.log(this.aaa); // console.log(this.props.aaa); } // 開始生成響應式資料 onReactived() { console.log(`on reactived ...`); } // 這裡 return 的資料會自動 merge 到 component public setup(props: any, ctx: any) { } // 在 setup 後 merge component 完成 // 可選 // public reactived() { // public reactived(data: ToRefs<this>) { public reactived(data: ToRefs<State>) { console.log(`reactived ...`); } // 資料初始化完成 返回到 上下文之前 // 未定義 State // public didReactived(data:ToRefs<this>) { // 以定義 State public didReactived(data: ToRefs<State>){ // 下面兩種等同 // watch(this.state.name, ()=>{ // console.log(`監聽修改 ...`); // }); watch(data.name, ()=>{ console.log(`監聽修改 ...`); }); console.log(`did reactived ...`); // 這裡一可以 return 初始資料 return data; } public edit() { console.log(11111, this.name, this.test); this.name++; this.object.time = (new Date).getTime(); this.test = !this.test; } public editProps(){ this.aaa += 100; } } </script>
- 繼承 使用 component/test3.vue
<template> <div>Test3 ...</div> <div>{{name}}</div> <div>{{object}}</div> </template> <script lang="ts"> import { Component, Mixin } from 'vue-pandora-decorators'; import Test2 from './test2.vue'; @Component export default class extends Mixin(Test2) { } </script>
- 不使用修飾器 home.vue
<template> <div>Dec ...</div> <div>{{name}}</div> <div>{{object}}</div> <test2 :aaa="aaa"></test2> <test3></test3> </template> <script lang="ts"> import { reactive, ref } from 'vue'; import Test1 from './components/test1.vue'; import Test2 from './components/test2.vue'; import Test3 from './components/test3.vue'; export default { components: { Test1, Test2, Test3, }, setup() { const aaa = ref(333); setInterval(()=>{ aaa.value ++; }, 1000); return { name: ref(111), object: reactive({}), aaa } } } </script>
vuex 修飾器使用
- 全域性 dynamic 模式
- 入口 store/index.ts
import { createStore } from 'vuex';
import { PermissionState } from './modules/permission';
export interface IRootState {
permission: PermissionState;
}
export default createStore<IRootState>({});
- store/modules/permission.ts
import { VuexModule, Module, Action, Mutation, getModule } from 'vue-pandora-decorators';
import store from '/@/store';
export interface PermissionState {
sessiontoken: string;
freshtoken: string;
roles: string[];
}
@Module({ dynamic: true, store, name: 'permission' })
class Permission extends VuexModule implements PermissionState {
public sessiontoken: string;
public freshtoken: string;
public roles: string[];
constructor(props: any) {
super(props);
this.sessiontoken = sessionStorage.getItem('sessiontoken') || '';
this.freshtoken = sessionStorage.getItem('freshtoken') || '';
this.roles = [];
// this.routes = constantRoutes.concat(asyncRoutes);
// this.dynamicRoutes = asyncRoutes;
}
@Action
public test(roles: string[]) {
console.log(this);
return this.setTest(roles);
}
@Mutation
private setTest(roles: string[]) {
console.log(roles);
this.roles = roles;
return roles;
}
// @Action
// public generateRoutes(roles: string[]) {
// let accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
// this.settingRoutes(accessedRoutes);
// }
// @Mutation
// private settingRoutes(routes: RouteConfig[]) {
// this.routes = constantRoutes.concat(routes);
// this.dynamicRoutes = routes;
// }
}
export const PermissionModule = getModule(Permission);
- 使用方法 隨便一個 vue 檔案
<template>
<div>
<div>{{roles}}</div>
<el-button @click="() => test(['1','2','3'])">Test</el-button>
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { PermissionModule } from '../store/modules/permission';
export default defineComponent({
setup() {
return {
roles: computed(() => PermissionModule.roles),
test: PermissionModule.test,
};
}
})
</script>
- 模組化非同步使用 在模組中非同步 注入
- 如 layout/store.ts
import { VuexModule, Module, Action, Mutation } from 'vue-pandora-decorators';
import store from '/@/store';
export interface LayoutState {
testObj: {
name: string;
test?: { name: string; }
};
}
@Module({ store })
export class Layout extends VuexModule implements LayoutState {
public testObj: { name: string; };
constructor(props: any) {
super(props);
this.testObj = { name: '111' };
}
@Action({ commit: 'testActionSuccess' })
public testAction(obj: string[]) {
return obj;
}
@Mutation
protected testActionSuccess(obj: string[]) {
this.testObj = { ...this.testObj, [(new Date).getTime()]: obj };
return this.testObj;
}
}
- layout/layout.vue
<template>
<div>
<div>{{roles}}</div>
<div>{{computed}}</div>
<el-button @click="() => test(['1','2','3'])">Test</el-button>
</div>
<!-- <div>
<div>{{testObj}}</div>
<el-button @click="() => editObj(['1','3'])">測試 Composition API</el-button>
</div>
<el-button @click="() => testAction(['1','3'])">測試 Vuex 抽離的控制器層</el-button> -->
<router-view />
</template>
<script lang="ts">
import { Component, PureComponent, state, computed } from 'vue-pandora-decorator';
import { PermissionModule } from '../store/modules/permission';
// import { Layout, LayoutState } from './store';
@Component
export default class extends PureComponent {
@state(()=> PermissionModule.roles)
public roles!: string[];
@computed
public get computed() {
return `${(new Date).getTime()}${(this.roles || []).join('')}`;
}
public get test() {
return PermissionModule.test;
};
constructor(props: any,ctx:any){
super(props,ctx);
this.roles = PermissionModule.roles;
}
}
// export default defineComponent({
// setup() {
// const state = useState<LayoutState>(Layout);
// useAction(Layout).testAction(['1','3']);
// const actions = useActions(Layout);
// return {
// roles: computed(() => PermissionModule.roles),
// ...state,
// test: PermissionModule.test,
// editObj: useAction(Layout).testAction,
// ...actions,
// };
// }
// })
</script>
</script>
在最後感謝一下 vuex-module-decorators 的作者
- 這裡偷懶直接使用大佬的 庫 十分感謝
- 後續迭代更多 需要支援的 API
- 最後再提一嘴 VUE 3.0 深入理解後確實不錯 一開始看到 這義大利麵條真心沒胃口
- 但經過思想鬥爭後 開始 開發這個外掛 寫到後面發現 面向物件與 Composition API 可以擦出別樣的火花
- 感謝尤大大
- 請根據自己喜好食用 ✌️