Heim  >  Fragen und Antworten  >  Hauptteil

VueJS behandelt Fehler in API-Aufrufen für Formularkomponenten

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粉964682904P粉964682904408 Tage vor511

Antworte allen(2)Ich werde antworten

  • P粉576184933

    P粉5761849332023-09-07 12:38:14

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

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

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

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

    errors.find(err => !!err.Password).Password
    

    Antwort
    0
  • P粉180844619

    P粉1808446192023-09-07 09:50:32

    反思你的代码

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

    - 使用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>

    Antwort
    0
  • StornierenAntwort