我有一個簡單的註冊端點,我希望允許用戶在我的 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粉5761849332023-09-07 12:38:14
看起來你正在回傳一個數組,而不是一個物件。
因此,要獲得存取權限,您需要執行errors[0].Password
。
您打算使用物件還是陣列(如果您有多個錯誤,可能會很有用)?
如果該陣列是預期的,並且您需要檢查 Password
屬性的所有錯誤,您將執行以下操作:
errors.find(err => !!err.Password).Password
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 文件
ref()
? 將 ref()
、reactive()
、compulated()
等保存的值儲存在無法修改的變數中。宣告這些變數時始終使用 const。
更多資訊 - StackOverflow 答案
// YOUR CODE let errors = ref({})
const errors = ref({})
您在一個實例中使用 .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>