解決 Vue3 中使用 VeeValidate 時發生的 'getInspectorTree' 錯誤

前言

這一篇會記錄一下使用 VeeValidate 時遇到的「An error occurred in hook 'getInspectorTree' with payload」該如何解決,順便記錄一下 VeeValidate 另一個奇妙的錯誤,也就是同名的 name 屬性問題。

backend.js: An error occurred in hook ‘getInspectorTree’ with payload

首先這個錯誤比較有點讓人茫然,而且普通狀況下你可能不會發生,因為這個錯誤是只有在你啟用 Vue Devtools 的 VeeValidate 之後才會發生的,如果你沒發生的話,那就是你沒有啟用 Vue Devtools 或者你沒有點一下 VeeValidate 的標籤,如下:

VeeValidate

當你點了之後再回到 Console 就會發現一推錯誤

1
2
3
An error occurred in hook 'getInspectorTree' with payload: {inspectorId: 'vee-validate-inspector', app: {…}, filter: '', rootNodes: Array(0)}

DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

下意識你可能會將錯誤訊息複製下來,然後去 Google 一下,但是你發現你找不到解決的方式因此這一邊我就來記錄一下解決方法。

解決方式

首先先來看一下我們範例程式碼目前是怎麼樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<VForm v-slot="{ errors }">
<div>
<label for="account">帳號</label>
<VField
id="account"
v-model.trim="user.account"
name="帳號"
type="email"
:class="{ 'is-invalid': errors['帳號'] }"
rules="required|email"
/>
<ErrorMessage name="帳號" />
</div>
<div>
<label for="password">密碼</label>
<VField
id="password"
v-model.trim="user.password"
name="密碼"
type="password"
:class="{ 'is-invalid': errors['密碼'] }"
rules="required"
/>
<ErrorMessage name="密碼" />
</div>
</VForm>
</template>

驗證

如果你要看完整版的話,可以到這邊看:vee-validate-error

可以看到我們的 Field 裡面有一個 name 屬性,這個 name 屬性是用來顯示錯誤訊息的,但是這個 name 屬性不能是中文,因為 VeeValidate 會將中文轉換,而這個轉換過程是導致出錯,因此這邊我們要將 name 屬性改成英文,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<VForm v-slot="{ errors }">
<div>
<label for="account">帳號</label>
<VField
id="account"
v-model.trim="user.account"
name="account"
type="email"
:class="{ 'is-invalid': errors.account }"
rules="required|email"
/>
<ErrorMessage
name="account"
/>
</div>
<div>
<label for="password">密碼</label>
<VField
id="password"
v-model.trim="user.password"
name="password"
type="password"
:class="{ 'is-invalid': errors.password }"
rules="required"
/>
<ErrorMessage name="password"/>
</div>
</VForm>
</template>

這樣子就不會出現錯誤了。

但是你會發現錯誤提示訊息變成英文的

英文

但是你還是期望它是中文的,那這時候我們可以增加一個屬性叫做 label,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<template>
<VForm v-slot="{ errors }">
<div>
<label for="account">帳號</label>
<VField
id="account"
v-model.trim="user.account"
name="account"
label="帳號"
type="email"
:class="{ 'is-invalid': errors.account }"
rules="required|email"
/>
<ErrorMessage
name="account"
/>
</div>
<div>
<label for="password">密碼</label>
<VField
id="password"
v-model.trim="user.password"
name="password"
label="密碼"
type="password"
:class="{ 'is-invalid': errors.password }"
rules="required"
/>
<ErrorMessage name="password"/>
</div>
</VForm>
</template>

這樣子就不會再噴 An error occurred in hook 'getInspectorTree' with payload: {inspectorId: 'vee-validate-inspector', app: {…}, filter: '', rootNodes: Array(0)} 的錯誤,而且也可以正常顯示中文

正常執行

除此之外 Vue Devtools 也可以正常顯示 vee-validate

vee-validate

name 屬性相同導致的錯誤

這是一個非常非常奇妙的錯誤,我們來看一下範例程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<VForm v-slot="{ errors }">
<h2>購買人資訊</h2>
<p>購買人信箱:{{ user }}</p>
<div>
<label for="account">購買人信箱</label>
<VField
id="email"
v-model.trim="user.email"
name="email"
label="帳號"
type="email"
:class="{ 'is-invalid': errors.email }"
rules="required|email"
/>
<ErrorMessage
name="email"
/>
</div>
<h2>寄送資訊</h2>
<p>收貨人信箱:{{ info }}</p>
<div>
<label for="account">收貨人信箱</label>
<VField
id="email"
v-model.trim="info.email"
name="email"
label="email"
type="email"
:class="{ 'is-invalid': errors.email }"
rules="required|email"
/>
<ErrorMessage
name="email"
/>
</div>
</VForm>
</template>

通常我們在做電商平台時,都會區分出一個是購買人資訊,一個是寄送資訊,接著我們 v-model 都是分別綁定到不同的資料,一個是綁定到 user,一個是綁定到 info,但是你會發現當你在輸入購買人信箱時,寄送資訊的收貨人信箱也會跟著變動

連動更新

解決方法

這時候你應該是百思不得其解,為什麼我們明明 v-model 綁定的是不同的資料,但是卻會連動更新呢?主要原因是出在 name 屬性上,因為我們兩個 VFieldname 都是 email,所以當你輸入購買人信箱時,寄送資訊的收貨人信箱也會跟著變動,所以我們只要把 name 改成不同的名稱就可以了,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<VForm v-slot="{ errors }">
<h2>購買人資訊</h2>
<p>購買人信箱:{{ user }}</p>
<div>
<label for="account">購買人信箱</label>
<VField
id="email"
v-model.trim="user.email"
name="userEmail"
label="帳號"
type="email"
:class="{ 'is-invalid': errors.userEmail }"
rules="required|email"
/>
<ErrorMessage
name="userEmail"
/>
</div>
<h2>寄送資訊</h2>
<p>收貨人信箱:{{ info }}</p>
<div>
<label for="account">收貨人信箱</label>
<VField
id="email"
v-model.trim="info.email"
name="infoEmail"
label="email"
type="email"
:class="{ 'is-invalid': errors.infoEmail }"
rules="required|email"
/>
<ErrorMessage
name="infoEmail"
/>
</div>
</VForm>
</template>

這時候你就可以正常輸入囉

正確綁定

這兩個 Vee-Validate 真的算是滿奇妙的,所以才特別寫一篇記錄下來,不然遲早會忘記,也希望可以幫助到遇到相同問題的人。

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ