传递给 Vuex 模块的函数后的 Vue TypeScript 未定义值

Vue TypeScript Undefined value after passing to function of Vuex module

我的组件中有一个名为 save 的异步函数

async save(): Promise<void> {
if (!this.ValidateForm()) {
  notifyError("", "Please enter all fields correctly");
}
else {
  await userModule.update(userModule.currentUser?.id as number, this.user, this.file);
  notifySuccess("Your profile updated");
}
}

当这一行执行时:

await userModule.update(userModule.currentUser?.id as number, this.user, this.file);

第二个和第三个参数的值在 userModule.update 中未定义。

另外我不得不说我没有使用任何箭头函数 我试过 console.log(this.user, this.file) 一切正常。

这是我的代码:

AccountSetting.ts HTML

<template>
  <div>
  <div class="row justify-content-center">
  <!-- left column -->
  <div class="col-md-6">
    <!-- general form elements -->
    <div class="card card-primary">
      <div class="card-header">
        <h3 class="card-title">Change your information</h3>
      </div>
      <!-- /.card-header -->
      <!-- form start -->
      <form>
        <div class="card-body">
          <div class="form-row">
            <div class="col form-group">
              <label>Username </label>
              <input
                type="text"
                v-model="user.username"
                @change="checkUsername()"
                class="form-control"
                placeholder="Enter new Username"
              />
              <small class="validation">{{ validations.username }}</small>
            </div>

            <div class="col form-group">
              <label>Profile Pricture </label>
              <div class="custom-file">
                <input
                  id="customFile"
                  type="file"
                  class="custom-file-input"
                  v-on:change="handleFileUpload($event)"
                  accept="image/*"
                />
                <label class="custom-file-label" for="customFile">{{
                  lblFilename
                }}</label>
              </div>
            </div>
          </div>

          <div class="form-row">
            <div class="col form-group">
              <label>Firstname </label>
              <input
                type="text"
                v-model="user.firstname"
                @change="checkFirstname()"
                class="form-control"
                placeholder="Enter your Firstname"
              />
              <small class="validation">{{ validations.firstname }}</small>
            </div>

            <div class="col form-group">
              <label>Lastname</label>
              <input
                type="text"
                v-model="user.lastname"
                @change="checkLastname()"
                class="form-control"
                placeholder="Enter your Lastname"
              />
              <small class="validation">{{ validations.lastname }}</small>
            </div>
          </div>

          <div class="form-row">
            <div class="col form-group">
              <label>Email </label>
              <input
                type="text"
                v-model="user.email"
                @change="checkEmail()"
                class="form-control"
                placeholder="Enter your Email address"
              />
              <small class="validation">{{ validations.email }}</small>
            </div>

            <div class="col form-group">
              <label>Phone Number</label>
              <input
                type="text"
                v-model="user.phoneNumber"
                @change="checkPhonenumber()"
                class="form-control"
                placeholder="Enter your Phone number"
              />
              <small class="validation">{{
                validations.phoneNumber
              }}</small>
            </div>
          </div>

          <div class="form-row">
            <div class="col form-group">
              <label>Birthdate </label>
              <input
                type="date"
                v-model="user.birthdate"
                class="form-control"
                placeholder=""
              />
            </div>

            <div class="col form-group">
              <label>Gender</label>
              <div class="form-control">
                <div class="form-check form-check-inline">
                  <label class="form-check-label pr-2" for="inlineRadioMale"
                    >Male</label
                  >
                  <input
                    id="inlineRadioMale"
                    type="radio"
                    name="gender"
                    value="1"
                    v-model="user.gender"
                    class="form-check-input"
                    checked
                  />
                </div>

                <div class="form-check form-check-inline">
                  <label
                    class="form-check-label pl-3 pr-2"
                    for="inlineRadioFemale"
                    >Female</label
                  >
                  <input
                    id="inlineRadioFemale"
                    type="radio"
                    name="gender"
                    value="2"
                    v-model="user.gender"
                    class="form-check-input"
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
        <!-- /.card-body -->

        <div class="card-footer">
          <button type="button" class="btn btn-primary" @click="save()">
            Save
          </button>
        </div>
      </form>
    </div>
    <!-- /.card -->
    </div>
   </div>
 </div>
  </template>

AccountSetting.ts 脚本

import { Component, Vue } from "vue-property-decorator";
import { UserUpdate } from "@/models/user/user";
import userModule from "@/store/modules/user";
import validationUtils from "@/common/validationUtils";
import { notifySuccess, notifyError } from 
"@/common/notificationUtils";
import GenderType from "@/common/Enums/genderType";
import { isNullOrEmpty } from "@/common/stringUtils";

@Component
export default class AccountSetting extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private file: any;
private lblFilename = "Choose file";
private user: UserUpdate = {
username: userModule.currentUser?.username as string,
firstname: userModule.currentUser?.firstname as string,
lastname: userModule.currentUser?.lastname as string,
email: userModule.currentUser?.email as string,
birthdate: userModule.currentUser?.birthdate as string,
phoneNumber: userModule.currentUser?.username as string,
gender: userModule.currentUser?.gender as GenderType,
teamId: userModule.currentUser?.teamId as number,
profilePictureId: userModule.currentUser?.profilePictureId as number,
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private validations: any = {
username: "",
password: "",
firstname: "",
lastname: "",
email: "",
phoneNumber: "",
};

checkUsername(): void {
if (!validationUtils.isValidUsername(this.user.username)) {
  this.validations.username = "Username is invalid";
}
else if (this.user.username.length == 0) {
  this.validations.username = "Username is invalid";
}
else if (this.user.username.length > 15) {
  this.validations.username = "Username should be less than 15 characters";
}
else {
  this.validations.username = "";
}
}

checkEmail(): void {
if (!validationUtils.isValidEmail(this.user.email)) {
  this.validations.email = "Email is invalid";
} else {
  this.validations.email = "";
 }
 }

checkFirstname(): void {
if (this.user.firstname.length == 0) {
  this.validations.firstname = "Firstname is invalid";
}
else if (this.user.firstname.length > 35) {
  this.validations.firstname = "Firstname should be less than 35 characters";
}
else {
  this.validations.firstname = "";
}
}

checkLastname(): void {
if (this.user.lastname.length == 0) {
  this.validations.lastname = "Lastname is invalid";
}
else if (this.user.firstname.length > 35) {
  this.validations.lastname = "Lastname should be less than 35 characters";
}
else {
  this.validations.lastname = "";
}
}

checkPhonenumber(): void {
if (this.user.phoneNumber.length == 0) {
  this.validations.phoneNumber = "Phone Number is invalid";
}
else {
  this.validations.phoneNumber = "";
}
}

ValidateForm(): boolean {
this.checkUsername();
this.checkFirstname();
this.checkLastname();
this.checkEmail();
this.checkPhonenumber();

if (this.user.username == "" || !isNullOrEmpty(this.validations.userUsername)) {
  return false;
}

if (this.user.firstname == "" || !isNullOrEmpty(this.validations.firstname)) {
  return false;
}

if (this.user.lastname == "" || !isNullOrEmpty(this.validations.lastname)) {
  return false;
}

if (this.user.email == "" || !isNullOrEmpty(this.validations.email)) {
  return false;
}

if (this.user.phoneNumber == "" || !isNullOrEmpty(this.validations.phoneNumber)) {
  return false;
}
return true;

}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
handleFileUpload(event: any): void {
this.file = event.target.files[0];
this.lblFilename = this.file.name;
}

async save(): Promise<void> {
if (!this.ValidateForm()) {
  notifyError("", "Please enter all fields correctly");
}
else {
  await userModule.update(userModule.currentUser?.id as number, this.user, this.file);
  notifySuccess("Your profile updated");
  }
 }

 }

Vuex 模块 user.ts :

import {
Action,
getModule,
Module,
Mutation,
VuexModule
} from "vuex-module-decorators";
import modulesNames from "@/store/moduleNames";
import store from "@/store/index";
import localStorageUtils from "@/common/localStorageUtils";
import { User, UserCreate, UserUpdate } from 
 "@/models/user/user";
import Token from "@/models/authentication/token";
import authenticationService from 
 "@/services/authentication/authenticationService";
import userService from "@/services/user/userService";
import Login from "@/models/user/login";
import { isEmptyObject } from "@/common/objectUtils";

@Module({ dynamic: true, namespaced: true, store, name: modulesNames.user })
class UserModule extends VuexModule {

private _currentUser?: User = localStorageUtils.getItem("User");
private _authToken?: Token = localStorageUtils.getItem("Token");

get currentUser(): User | undefined | null {
    return this._currentUser;
}

get authToken(): Token | undefined | null {
    return this._authToken;
}

get isLoggedIn(): boolean {
    return !isEmptyObject(this.currentUser);
}

@Mutation
private SET_CURRENT_USER(currentUser?: User): void {
    if (currentUser) {
        this._currentUser = currentUser;
        localStorageUtils.setItem("User", currentUser);
    } else {
        this._authToken = undefined;
        localStorageUtils.removeItem("User");
    }
}

@Mutation
private SET_AUTH_TOKEN(authToken?: Token): void {
    if (authToken) {
        this._authToken = authToken;
        localStorageUtils.setItem("Token", authToken);
    } else {
        this._authToken = undefined;
        localStorageUtils.removeItem("Token");
    }
}

@Action({ rawError: true })
public async login(login: Login): Promise<void> {
    const response = await authenticationService.login(login);
    this.SET_CURRENT_USER(response);
}

@Action({ rawError: true })
public async register(userCreateOrUpdate: UserCreate): Promise<void> {
    const response = await authenticationService.register(userCreateOrUpdate);
    this.SET_CURRENT_USER(response);
}

@Action({ rawError: true })
public async update(id: number, userUpdate: UserUpdate, file: any): Promise<void> {
    const response = await userService.updateUser(id, userUpdate, file);
    this.SET_CURRENT_USER(response);
}

@Action({ rawError: true })
public async logout(): Promise<void> {
    await authenticationService.logout();
    this.SET_AUTH_TOKEN(undefined);
    this.SET_CURRENT_USER(undefined);
}

}

export default getModule(UserModule);

index.ts

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {},
});

modulesNames.ts :

const modulesNames = {
user: "user",
};

export default modulesNames;

我是 javascript 以及打字稿和前端框架的新手。

在 Whosebug 中多次尝试解决此问题后,还阅读了文档 ,我什么也没发现,所以我决定做更多的调试,我明白了 Vuex 操作仅接受一个参数,因此另一个参数值未定义