vee-validate + vuetify 文本输入字段 → 如何迁移到新版本?

问题描述 投票:0回答:2

我有一个旧的

Vue2
登录页面代码。其中一部分正在检查用户名输入字段:

...
<validation-observer ref="ref-id" v-slot="{ invalid }">
  <v-form>
    <v-card-text>
      <validation-provider
        v-slot="{ errors }"
        rules="rulename"
        name="username"
      >
        <v-text-field
          v-model="input.username"
          label="username"
          prepend-icon="mdi-account-circle"
          :error-messages="errors"
        ></v-text-field>
      </validation-provider>
      ...
    </v-card-text>
  </v-form>
</validation-observer>
...

现在我正在尝试使用新版本创建相同的代码

Vuetify
vee-validate
3
4

我可以使用新版本的

v-text-field
创建
Vuetify
:

<vee-validation-form as="v-form">
  <v-card-text>
    <!-- <vee-validation-field as="v-text-field" -->
    <v-text-field
      v-model="input.username"
      label="username"
      prepend-icon="mdi-account-circle"
      :error-messages="errors"
    ></v-text-field>
    <!-- ></vee-validation-field> -->
  </v-card-text>
</vee-validation-form>

哪里

  • vee-validation-form
    Form
  • vee-validation-field
    Field

此代码至少显示

username
输入元素。

但是当我尝试使用

<vee-validation-field as="v-text-field"
而不是
<v-text-field
时,它显示错误:

ERROR
Cannot read properties of undefined (reading 'split')
TypeError: Cannot read properties of undefined (reading 'split')
    at normalizeFormPath (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:100:26)
    at ReactiveEffect.eval [as fn] (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:1603:70)
    at ReactiveEffect.run (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:217:19)
    at get value [as value] (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:1178:33)
    at unref (webpack-internal:///./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js:1057:29)
    at _useFieldValue (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:1141:70)
    at useFieldState (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:1044:54)
    at _useField (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:1618:72)
    at useField (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:1597:12)
    at setup (webpack-internal:///./node_modules/vee-validate/dist/vee-validate.esm.js:2038:164)

问题是:如何将

v-text-field
组件与
vee-validate
一起使用?据我正确理解,新的
ValidationObserver
中没有
ValidationPbserver
vee-validate v4
组件。

vue.js vuetify.js vee-validate
2个回答
1
投票

Field 组件需要一个

name
属性,当它尝试对值调用
split()
时会抛出错误。只需设置一个名称,错误就消失了:

<Field as="v-text-field" 
  name="username"
  ...
></Field>

但是,

label
Field
组件的道具,但它仅将属性(即非道具)传递给自定义输入组件(请参阅code),因此您无法将标签传递给v-text -场地。此外,您还必须通过表格获取错误消息。

目前看来使用

:as
比解决方案更麻烦。可能更好地坚持使用插槽:

<vee-validation-field
  v-slot="{ field, errors }"
  name="username"
  rules="required|needsL"
  v-model="username"
>
  <v-text-field
    v-model="field.value"
    v-bind="field"
    label="username"
    prepend-icon="mdi-account-circle"
    :error-messages="errors"
  />
</vee-validation-field>

(由于 vee-validate 中的

 问题
,VTextField 上有些重复的
v-bind
v-model 对于他们来说是必要的)

const { createApp, ref } = Vue;
const { createVuetify } = Vuetify
const vuetify = createVuetify()

VeeValidate.defineRule('required', VeeValidateRules.required)
VeeValidate.defineRule('needsL', v => v.toLowerCase().includes('L') || 'Input something with an `l`')

const app = {
  components: {
    'vee-validation-form': VeeValidate.Form,
    'vee-validation-field': VeeValidate.Field,
  },
  setup(){
    return {
      username1: ref('user 1'),
      username2: ref('user 2'),
    }
  }

}
createApp(app).use(vuetify).mount('#app')
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
  <v-app>
    <v-main>
      <vee-validation-form as="v-form" v-slot="{errors}">
        <v-card-text>
        Field from :as
          <vee-validation-field as="v-text-field" 
            name="username1"
            v-model="username1"
            prepend-icon="mdi-account-circle"
            :error-messages="errors.username1"
            rules="required|needsL"
          ></vee-validation-field>
          
          Field in slot
          <vee-validation-field
            v-slot="{ field, errors }"
            v-model="username2"
            name="username2"
            rules="required|needsL"
          >
            <v-text-field
              v-model="field.value"
              v-bind="field"
              label="username"
              prepend-icon="mdi-account-circle"
              :error-messages="errors"
            />
          </vee-validation-field>
          
        </v-card-text>
      </vee-validation-form>

    </v-main>
  </v-app>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@3/dist/vuetify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vee-validate/4.10.8/vee-validate.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@vee-validate/[email protected]/dist/vee-validate-rules.min.js"></script>


0
投票

总的来说,上述方法是正确的,但犯了一个重大错误。

就在一周前,我不得不处理我们的大型项目的迁移,该项目有大量的形式,从 Vuetify 2 到 3,从 Vee-validate 3 到 4。在花费了相当多的时间之后,我想提出以下建议研究问题和处理具体案例的时间。我不会继承之前的答案,而是会在一条消息中概述我的整个解决方案,方便寻求答案的人立即掌握主题。

在确定validation-observer和validation-provider组件时,一切都是准确的。就我而言,我注册了名为 和 的 Form 组件和 Field 。对于那些迁移真实项目的人来说,这将节省大量时间,避免重写组件名称。

app
.component('validation-observer', Form)
.component('validation-provider', Field)

现在,我们应该将 Field 组件视为主要输入组件,而 v-text-field 只是一个视觉对象,它仅与 Field 交换数据,而 Field 现在是验证提供程序。

根据文档,我们可以通过插槽与验证提供程序和我们的字段进行交互,但不是field,而是componentField。它将包含带有 modelValue 键而不是 value 的正确对象,使我们能够正确访问组件的值。这确保了与 Vue 3 的正确兼容性,因为在 2 版本中使用了 value。因此,默认情况下不需要使用 as 参数。包含内部组件的 Field 组件不会显示为标准输入字段,我们在输入组件中通过 v-bind 使用 componentField 插槽。

所以我们需要采取2个行动:

  1. v-model 移动到 Field 组件
  2. v-bind 添加到我们的输入字段

以下是正确代码的示例(如果需要,请使用您的组件名称):

<validation-observer
    v-slot="{ handleSubmit }"
>
   <validation-provider
            v-slot="{ componentField, errors }"
            v-model="input.username"
            name="Username"
            rules="required"
        >
    <v-text-field
      v-bind="componentField"
      :error-messages="errors"
      label="Username"
      prepend-icon="mdi-account-circle"
    />
    </validation-provider>
</validation-observer>

现在我们的字段已经与验证组件Field(validation-provider)正确同步了。

对于字段(验证观察者)插槽,请参阅文档

© www.soinside.com 2019 - 2024. All rights reserved.