首頁  >  問答  >  主體

VueJS 處理表單元件上 api 呼叫的錯誤

我有一個簡單的註冊端點,我希望允許用戶在我的 vue 應用程式中註冊,我還想從我的後端向 vue 用戶端顯示適當的錯誤。

錯誤 JSON 結構如下:

{
    "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"
        ]
    }
}

我有一個帶有這樣的暫存器函數的可組合項:

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
    }
}

我還有一個表單元件,它只是一個添加了 v-models 的簡單表單:

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

在我的可組合項目中,我可以像這樣註銷錯誤回應

錯誤回應

我嘗試在表單元件中登出錯誤,但現在我只是得到一個空物件(我正在使用反應式來處理可組合項中的此錯誤物件)

來自可組合項目的空物件回應

P粉964682904P粉964682904408 天前509

全部回覆(2)我來回復

  • P粉576184933

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

    看起來你正在回傳一個數組,而不是一個物件。

    因此,要獲得存取權限,您需要執行errors[0].Password

    您打算使用物件還是陣列(如果您有多個錯誤,可能會很有用)?

    如果該陣列是預期的,並且您需要檢查 Password 屬性的所有錯誤,您將執行以下操作:

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

    回覆
    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>

    回覆
    0
  • 取消回覆