VueJS behandelt Fehler in API-Aufrufen für Formularkomponenten
P粉964682904
P粉964682904 2023-09-06 22:01:08
0
2
578

Ich habe einen einfachen Registrierungsendpunkt, den ich Benutzern ermöglichen möchte, sich in meiner Vue-App zu registrieren. Außerdem möchte ich dem Vue-Client von meinem Backend aus entsprechende Fehler anzeigen.

Die Fehler-JSON-Struktur sieht folgendermaßen aus:

{
    "errors": {
        "Password": [
            "Password is required",
            "Minimum length of 8 characters is required"
        ],
        "UserName": [
            "Username is required",
            "Minimum length of 6 characters is required"
        ],
        "EmailAddress": [
            "Email Address is required",
            "Invalid Email Address"
        ],
        "ConfirmPassword": [
            "Confirm Password is required"
        ]
    }
}

Ich habe ein Composable mit einer Registerfunktion wie dieser:

export default function useAuth() {

    let errors = ref({}) 

    const register = (request) => {

        errors = {}
        AuthService.register(request)
            .then(res => {
                console.log("res: "+ res)
            })
            .catch(err => {
                const errList = err.response.data.errors;
                errors = errList
                // Here i'm getting a reponse
                console.log(errors)

            })
    }
    return {
        register, errors
    }
}

Ich habe auch eine Formularkomponente, die nur ein einfaches Formular mit hinzugefügten V-Modellen ist:

<script>
// Imports..
export default {
  components: {},
  setup() {

    const { register, errors} = useAuth();

    const request = {
      userName: "",
      emailAddress: "",
      password: "",
      confirmPassword: "",
    };


    const handleSubmit = () => {
        register(request);
        // empty object
        console.log(errors)
      
    };

    return {
      errors,
      request,
      handleSubmit
      
    };
  },
};
</script>

In meinem Composable kann ich die Fehlerantwort so abmelden

Fehlerantwort

Ich habe versucht, die Registrierung des Fehlers in der Formularkomponente aufzuheben, aber jetzt erhalte ich nur ein leeres Objekt (ich verwende reaktiv, um dieses Fehlerobjekt im Composable zu behandeln)

Leere Objektantwort von zusammensetzbaren Elementen

P粉964682904
P粉964682904

Antworte allen(2)
P粉576184933

看起来你正在返回一个数组,而不是一个对象。

因此,要获得访问权限,您需要执行errors[0].Password

您打算使用对象还是数组(如果您有多个错误,可能会很有用)?

如果该数组是预期的,并且您需要检查 Password 属性的所有错误,您将执行如下操作:

errors.find(err => !!err.Password).Password
P粉180844619

反思你的代码

其中存在多个错误,使我很难提供适合您需求的简洁答案。相反,我快速整理了一个根据您的原则工作的代码片段。展望未来,我将尽力强调需要注意的事项,并为未来提供一些好的建议。

- 使用async function()可以等待Promise

的响应
不好(如果您想立即使用结果,目前 console.log 证明使用async
// YOUR CODE
const handleSubmit = () => {
  register(request); // call PROMISE () 
  // empty object
  console.log(errors)
};

这并不能立即提供结果;它需要一些时间在单独的线程上运行。结果,JavaScript 脚本几乎立即向前移动。通常,如果您想立即使用结果,这将导致错误,因为响应尚未到达。

因此,当您尝试访问 errors 的新结果时,您会看到它是空的,即使在 console.log 之后,1-2 秒后,它不会再为空,因为 register() 已经执行完毕。

好的
// SUCCESSFULLY USING
const handleSubmit = async () => {
  await register(request); // call PROMISE () AND WAIT response by await
  // empty object
  console.log(errors)
};

等待 -等待进程结束 - MDN 文档
异步函数 - 需要什么await 使用 - MDN 文档

- 如何在 VueJS 上使用 ref()

1.

ref()reactive()compulated() 等保存的值存储在无法修改的变量中。声明这些变量时始终使用 const。

更多信息 - StackOverflow 答案

不好
// YOUR CODE
let errors = ref({})
好的
const errors = ref({})
2.

您在一个实例中使用 .value 后缀,而在另一实例中则不使用。嗯,情况是 ref() 变量的结果始终存储在 .value 中。您可以相应地操纵它。

不好
// YOUR CODE
let errors = ref({})

// and...
errors = {...}
好的
const errors = ref({})

// and...
errors.value = {...}

如何使用 ref() - VueJS 文档



具有概述逻辑的示例代码

我对这些行进行了注释,以便更好地理解代码。我希望这是可以理解的。

/**
 ** Need more function for example
 ** !!! The vue is below !!!
 */

// CDN Vue Import
const { createApp, ref, computed } = Vue

// isValideEmail() (JUST EXAMPLE FOR SNIPPET)
// Helper function to validate email address
function isValidEmail(email) {
  const emailRegex = /^\S+@\S+\.\S+$/;
  return emailRegex.test(email);
}

// AuthService (JUST EXAMPLE FOR SNIPPET)
class AuthServiceClass {
  errors
  
  constructor() {
    this.errors = {};
  }

  register(inputs) {
    // Reset Errors
    this.errors = {};
    
    console.log(inputs)
    
    // Check the UserName field
    if (!inputs.userName) {
      this.errors.UserName = (this.errors?.UserName ?? []).concat("Username is required");
    }
    if (!inputs.userName || inputs.userName.length < 6) {
      this.errors.UserName = (this.errors?.UserName ?? []).concat("Minimum length of 6 characters is required");
    }

    // Check the EmailAddress field
    if (!inputs.emailAddress) {
      this.errors.EmailAddress = (this.errors?.EmailAddress ?? []).concat("Email Address is required");
    }
    if (!inputs.emailAddress || !isValidEmail(inputs.emailAddress)) {
      this.errors.EmailAddress = (this.errors?.EmailAddress ?? []).concat("Invalid Email Address");
    }

    // Check the Password field
    if (!inputs.password) {
      this.errors.Password = (this.errors?.Password ?? []).concat("Password is required");
    }
    if (!inputs.password || inputs.password.length < 8) {
      this.errors.Password = (this.errors?.Password ?? []).concat("Minimum length of 8 characters is required");
    }

    // Check the ConfirmPassword field
    if (!inputs.confirmPassword) {
      this.errors.ConfirmPassword = (this.errors?.ConfirmPassword ?? []).concat("Confirm Password is required");
    }
    
    // Return with Promise because its just a simulate your really AuthService.register
    return new Promise((resolve, reject) => {
      if (this.errors.length !== 0) {
        reject({ errors: this.errors });
      } else {
        resolve({ success: true, errors: null });
      }
    });
  }
}
// Import AuthService (JUST EXAMPLE FOR SNIPPET)
const AuthService = new AuthServiceClass()

// Declare useAuth() (JUST EXAMPLE FOR SNIPPET)
function useAuth()
{
    const errors = ref({}) 

    const register = async (request) => {
        await AuthService.register(request)
          .then(res => {
            console.log("AuthService Register Successfully Response", res)
          })
          .catch(err => {
            console.log("AuthService Register Error Response", err)
            const newErrors = err.errors;
            errors.value = newErrors
          })
    }
    
    return { register, errors }
}

/**
 ** !!!!!!
 ** Here's started vue code snippet
 */

// Component.vue
const app = createApp({
  setup() {
    // Get register() and errors Ref
    const { register, errors } = useAuth();

    // Declare Ref Object for inputs
    const request = ref({
      userName: "",
      emailAddress: "",
      password: "",
      confirmPassword: "",
    });

    // Declare Submit Function (async for Promise check !!!)
    const handleSubmit = async () => {
        console.log('') // just log
        console.log('Detect New Handle') // just log

        // call register() function with our value of inputs
        // wait answer by "await"
        await register(request.value);

        console.log('HandleSubmit - Check Error List', errors.value) // just log
    };
    
    // Just Extra Computed Value, not important
    // return true/false
    const hasError = computed(() => Object.keys(errors.value).length > 0)
    
    return { hasError, errors, request, handleSubmit }
  },
}).mount('#app')
.input {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 10px;
  max-width: 200px;
}

.error {
  color: red;
}
<!-- Component.vue -->

<script src="https://unpkg.com/vue@3.3.4/dist/vue.global.prod.js"></script>

<div id="app">
  <div>
    <!-- Display Errors -->
    <div v-if="hasError">
      <!-- errors is an object, so you can foreach its keys -->
      <div v-for="inputName of Object.keys(errors)">
        <span>{{ inputName }}:</span>
        <!-- name-array pairs can be directly printed as error messages -->
        <div v-for="errorMessage of errors[inputName]" class="error">
          {{ errorMessage }}
        </div>
      </div>
    </div>
    <!-- Inputs -->
    <!-- request is an object, so you can foreach its keys -->
    <div class="input" v-for="inputName of Object.keys(request)">
      <label>{{ inputName }}</label>
      <input v-model="request[inputName]" />
    </div>
    <!-- Submit Button -->
    <button @click="handleSubmit">Submit</button>
  </div>
</div>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage