vuex-module-decorators官网:https://gitcode.net/mirrors/championswimmer/vuex-module-decorators?utm_source=csdn_github_accelerator
npm安装:
npm install vuex-module-decorators
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'
@Module
export default class Counter2 extends VuexModule {
count = 0
@Mutation
increment(delta: number) {
this.count += delta
}
@Mutation
decrement(delta: number) {
this.count -= delta
}
@Action({ commit: 'increment' })
incr() {
return 5
}
@Action({ commit: 'decrement' })
decr() {
return 5
}
}
import { Module, VuexModule } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
}
等同于下面的代码
export default {
state: { wheels: 2 }
}
import { Module, VuexModule } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
get axles() {
return this.wheels / 2
}
}
等同于下面的代码
export default {
state: { wheels: 2 },
getters: {
axles: (state) => state.wheels / 2
}
}
import { Module, VuexModule, Mutation } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
@Mutation
puncture(n: number) {
this.wheels = this.wheels - n
}
}
等同于下面的代码
export default {
state: { wheels: 2 },
mutations: {
puncture: (state, payload) => {
state.wheels = state.wheels - payload
}
}
}
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'
import { get } from 'request'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
@Mutation
addWheel(n: number) {
this.wheels = this.wheels + n
}
@Action
async fetchNewWheels(wheelStore: string) {
const wheels = await get(wheelStore)
this.context.commit('addWheel', wheels)
}
}
等同于下面的代码
const request = require('request')
export default {
state: { wheels: 2 },
mutations: {
addWheel: (state, payload) => {
state.wheels = state.wheels + payload
}
},
actions: {
fetchNewWheels: async (context, payload) => {
const wheels = await request.get(payload)
context.commit('addWheel', wheels)
}
}
}
在vuex中是要通过commit来更改state中的数据.在vuex-module-decorators中有MutationAction修饰器,可以直接修改state数据
export default class PassengerStore extends VuexModule {
public username = '';
public password = '';
//'username'和'password'被返回的对象替换,
//格式必须为`{username:...,password:...}`
@MutationAction({ mutate: ['username', 'password'] })
async setPassenger(name: string) {
const response: any = await request(name); // 接口返回 [{name:'愚公',password:'123456'}]
// 此处返回值必须和上面mutate后面的名称保持一致;
return {
username: response[0].name,
password: response[0].password,
};
}
}
// index.vue中使用
<template>
<div class="">
用户名:{{PassengerStoreModule.username}}<br/>
密码:{{PassengerStoreModule.password}}<br/>
<button @click="getPassenger()">getPassenger</button>
</div>
</template>
...
@Component
export default class IndexPage extends Vue {
private PassengerStoreModule: any = PassengerStoreModule;
getPassenger() {
PassengerStoreModule.setPassenger('愚公');
}
}
传统是需要注册到的new Vuex.Store上,然后通过this$store访问,使用getModule访问类型更加安全,可以
再module上使用store模块,然后getModule(模块名)也可以getModule(模块名,this.$store)的形式
import { Module, VuexModule, getModule } from 'vuex-module-decorators'
import store from '@/store'
// 1. module上使用store
@Module({ dynamic: true, store, name: 'mymod' })
class MyModule extends VuexModule {
someField: number = 10
}
const myMod = getModule(MyModule)
myMod.someField //works
myMod.someOtherField //Typescript will error, as field doesn't exist
// 2. module上不使用store, getModule使用store
@Module({ dynamic: true, name: 'mymod' })
class MyModule extends VuexModule {
someField: number = 10
}
const myMod = getModule(MyModule,store)
动态模块使用
import {Module,VuexModule,Mutation,Action,getModule,} from 'vuex-module-decorators';
// import store from '@/store'; // 去掉store
type User = { username: string; password: string; }
@Module({name: 'user', namespaced: true,})
export default class PassengerStore extends VuexModule {
// ...同上方案例一模一样
}
// 因为getModule是要对应store的.上面去掉了store,所以也要去掉 getModule,
// export const PassengerStoreModule = getModule(PassengerStore);
// store/index.ts
import Vue from 'vue';
import Vuex from 'vuex';
import PassengerStore from './modules/passenger';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user: PassengerStore
},
});
//index.vue 使用
import PassengerStore from '@/store/modules/passenger';
import { getModule } from 'vuex-module-decorators';
...
created() {
const PassengerStoreModule = getModule(PassengerStore, this.$store);
console.log(PassengerStoreModule.loginInfo);
PassengerStoreModule.getZhangsan();
PassengerStoreModule.getLisi();
console.log(PassengerStoreModule.userNumber);
}
import ApiService from "@/core/services/ApiService";
import JwtService from "@/core/services/JwtService";
import { Actions, Mutations } from "@/store/enums/StoreEnums";
import { Module, Action, Mutation, VuexModule } from "vuex-module-decorators";
//用户接口
export interface User {
name: string;
surname: string;
email: string;
password: string;
token: string;
}
//用户权限信息接口
export interface UserAuthInfo {
errors: Array<string>;
user: User;
isAuthenticated: boolean;
}
//动态创建权限模块
@Module
export default class AuthModule extends VuexModule implements UserAuthInfo {
errors = [];
user = {} as User;
isAuthenticated = !!JwtService.getToken();
/**
* 获取当前用户对象
* @returns User
*/
get currentUser(): User {
return this.user;
}
/**
* 验证用户身份验证
* @returns boolean
*/
get isUserAuthenticated(): boolean {
return this.isAuthenticated;
}
/**
* 获取身份验证错误
* @returns array
*/
get getErrors(): Array<string> {
return this.errors;
}
/**
* 设置错误信息
* @param error string
*/
@Mutation
[Mutations.SET_ERROR](error) {
this.errors = error;
}
/**
* 设置令牌
* @param user 用户信息
*/
@Mutation
[Mutations.SET_AUTH](user) {
this.isAuthenticated = true;
this.user = user;
this.errors = [];
JwtService.saveToken(this.user.token);
}
/**
* 设置用户
* @param use 用户信息
*/
@Mutation
[Mutations.SET_USER](user) {
this.user = user;
}
/**
* 设置密码
* @param password 密码
*/
@Mutation
[Mutations.SET_PASSWORD](password) {
this.user.password = password;
}
/**
* 删除令牌
*/
@Mutation
[Mutations.PURGE_AUTH]() {
this.isAuthenticated = false;
this.user = {} as User;
this.errors = [];
JwtService.destroyToken();
}
/**
* 用户登录
* @param credentials 登录信息
* @returns 返回登录状态
*/
@Action
[Actions.LOGIN](credentials) {
return new Promise<void>((resolve, reject) => {
ApiService.post("login", credentials)
.then(({ data }) => {
this.context.commit(Mutations.SET_AUTH, data);
resolve();
})
.catch(({ response }) => {
this.context.commit(Mutations.SET_ERROR, response.data.errors);
reject();
});
});
}
/**
* 用户退出
*/
@Action
[Actions.LOGOUT]() {
this.context.commit(Mutations.PURGE_AUTH);
}
/**
* 用户注册
* @param credentials 用户注册信息
* @returns
*/
@Action
[Actions.REGISTER](credentials) {
return new Promise<void>((resolve, reject) => {
ApiService.post("registration", credentials)
.then(({ data }) => {
this.context.commit(Mutations.SET_AUTH, data);
resolve();
})
.catch(({ response }) => {
this.context.commit(Mutations.SET_ERROR, response.data.errors);
reject();
});
});
}
/**
* 设置密码
* @param payload 用户信息
* @returns
*/
@Action
[Actions.FORGOT_PASSWORD](payload) {
return new Promise<void>((resolve, reject) => {
ApiService.post("forgot_password", payload)
.then(({ data }) => {
this.context.commit(Mutations.SET_AUTH, data);
resolve();
})
.catch(({ response }) => {
console.log(response.data.errors);
this.context.commit(Mutations.SET_ERROR, response.data.errors);
reject();
});
});
}
/**
* 校验权限
*/
@Action
[Actions.VERIFY_AUTH]() {
if (JwtService.getToken()) {
ApiService.setHeader();
ApiService.get("verify")
.then(({ data }) => {
this.context.commit(Mutations.SET_AUTH, data);
})
.catch(({ response }) => {
this.context.commit(Mutations.SET_ERROR, response.data.errors);
});
} else {
this.context.commit(Mutations.PURGE_AUTH);
}
}
/**
* 更新用户信息
* @param payload 用户信息
* @returns 返回结果
*/
@Action
[Actions.UPDATE_USER](payload) {
ApiService.setHeader();
return new Promise<void>((resolve, reject) => {
ApiService.post("update_user", payload)
.then(({ data }) => {
this.context.commit(Mutations.SET_USER, data);
resolve();
})
.catch(({ response }) => {
this.context.commit(Mutations.SET_ERROR, response.data.errors);
reject();
});
});
}
}
enum Actions {
// action types
ADD_BODY_CLASSNAME = "addBodyClassName",
REMOVE_BODY_CLASSNAME = "removeBodyClassName",
ADD_BODY_ATTRIBUTE = "addBodyAttribute",
REMOVE_BODY_ATTRIBUTE = "removeBodyAttribute",
ADD_CLASSNAME = "addClassName",
VERIFY_AUTH = "verifyAuth",
LOGIN = "login",
LOGOUT = "logout",
REGISTER = "register",
UPDATE_USER = "updateUser",
FORGOT_PASSWORD = "forgotPassword",
SET_BREADCRUMB_ACTION = "setBreadcrumbAction"
}
enum Mutations {
// mutation types
SET_CLASSNAME_BY_POSITION = "appendBreadcrumb",
PURGE_AUTH = "logOut",
SET_AUTH = "setAuth",
SET_USER = "setUser",
SET_PASSWORD = "setPassword",
SET_ERROR = "setError",
SET_BREADCRUMB_MUTATION = "setBreadcrumbMutation",
SET_LAYOUT_CONFIG = "setLayoutConfig",
RESET_LAYOUT_CONFIG = "resetLayoutConfig",
OVERRIDE_LAYOUT_CONFIG = "overrideLayoutConfig",
OVERRIDE_PAGE_LAYOUT_CONFIG = "overridePageLayoutConfig"
}
export { Actions, Mutations };
import { createStore } from "vuex";
import { config } from "vuex-module-decorators";
import AuthModule from "@/store/modules/AuthModule";
config.rawError = true;
const store = createStore({
modules: {
AuthModule
}
});
export default store;
import { createApp } from "vue";
import App from "./App.vue";
/*
TIP: To get started with clean router change path to @/router/clean.ts.
*/
import router from "./router";
import store from "./store";
import ElementPlus from "element-plus";
import i18n from "@/core/plugins/i18n";
//imports for app initialization
import MockAdapter from "@/core/mock/MockService";
import ApiService from "@/core/services/ApiService";
import { initApexCharts } from "@/core/plugins/apexcharts";
import { initInlineSvg } from "@/core/plugins/inline-svg";
import { initVeeValidate } from "@/core/plugins/vee-validate";
import "@/core/plugins/keenthemes";
import "@/core/plugins/prismjs";
import "bootstrap";
const app = createApp(App);
app.use(store);
app.use(router);
app.use(ElementPlus);
ApiService.init(app);
MockAdapter.init(app);
initApexCharts(app);
initInlineSvg(app);
initVeeValidate();
app.use(i18n);
app.mount("#app");
<script lang="ts">
import { defineComponent, ref } from "vue";
import { ErrorMessage, Field, Form } from "vee-validate";
import { Actions } from "@/store/enums/StoreEnums";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import Swal from "sweetalert2/dist/sweetalert2.min.js";
import * as Yup from "yup";
export default defineComponent({
name: "sign-in",
components: {
Field,
Form,
ErrorMessage
},
setup() {
const store = useStore();
const router = useRouter();
const submitButton = ref<HTMLElement | null>(null);
//创建表单验证对象
const login = Yup.object().shape({
email: Yup.string()
.email()
.required()
.label("Email"),
password: Yup.string()
.min(4)
.required()
.label("Password")
});
//表单提交功能
const onSubmitLogin = values => {
// 清除现有错误
store.dispatch(Actions.LOGOUT);
setTimeout(() => {
store
.dispatch(Actions.LOGIN, values)
.then(() => {
Swal.fire({
text: "All is cool! Now you submit this form",
icon: "success",
buttonsStyling: false,
confirmButtonText: "Ok, got it!",
customClass: {
confirmButton: "btn fw-bold btn-light-primary"
}
}).then(function() {
router.push({ name: "dashboard" });
});
})
.catch(() => {
Swal.fire({
text: store.getters.getErrors[0],
icon: "error",
buttonsStyling: false,
confirmButtonText: "Try again!",
customClass: {
confirmButton: "btn fw-bold btn-light-danger"
}
});
});
}, 2000);
};
return {
onSubmitLogin,
login,
submitButton
};
}
});
</script>