You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue项目中如何为使用CInput的现有表单集成vee-validate v4校验?

你的代码需要针对vee-validate的规则做适配,操作步骤和修改后的代码如下:


前置确认

vee-validate v4仅支持Vue3,如果你当前项目使用的是Vue2,请执行以下命令安装适配Vue2的版本:
npm install vee-validate@3 @vee-validate/rules@3 --save

以下是Vue3 + vee-validate v4的适配方案:


1. 安装校验规则包

执行命令安装官方预设的校验规则:
npm install @vee-validate/rules --save

2. 完整修改后的代码

template部分

<template>
  <CRow>
    <CCol col="12" lg="6">
      <CCard no-header>
        <CCardBody>
          <h3>创建笔记</h3>
          <CAlert
            :show.sync="dismissCountDown"
            color="primary"
            fade
          >
            ({{ dismissCountDown }}) {{ message }}
          </CAlert>

          <!-- 用Form组件包裹所有表单元素 -->
          <Form v-slot="{ errors, handleSubmit }" @submit="handleSubmit(store)">
            <Field
              as="CInput"
              name="title"
              rules="required"
              label="标题"
              type="text"
              id="title"
              placeholder="请输入标题"
              v-model="note.title"
            ></Field>
            <!-- 错误提示 -->
            <span class="text-danger small" v-if="errors.title">{{ errors.title }}</span>

            <Field
              as="CInput"
              name="content"
              rules="required"
              textarea="true"
              label="内容"
              id="content"
              :rows="9"
              placeholder="请输入内容.."
              v-model="note.content"
            ></Field>
            <span class="text-danger small" v-if="errors.content">{{ errors.content }}</span>

            <Field
              as="CInput"
              name="applies_to_date"
              rules="required"
              label="适用日期"
              type="date"
              id="applies_to_date"
              v-model="note.applies_to_date"
            ></Field>
            <span class="text-danger small" v-if="errors.applies_to_date">{{ errors.applies_to_date }}</span>

            <Field
              as="CSelect"
              name="status_id"
              rules="required"
              id="status_id"
              label="状态"
              :value.sync="note.status_id"
              :plain="true"
              :options="statuses"
            >
            </Field>
            <span class="text-danger small" v-if="errors.status_id">{{ errors.status_id }}</span>

            <Field
              as="CInput"
              name="note_type"
              rules="required"
              label="笔记类型"
              type="text"
              id="note_type"
              v-model="note.note_type"
            ></Field>
            <span class="text-danger small" v-if="errors.note_type">{{ errors.note_type }}</span>

            <div id="app">
              <ckeditor v-model="editorData" :config="editorConfig"></ckeditor>
            </div>

            <!-- 提交按钮改成submit类型 -->
            <CButton color="primary" type="submit">创建</CButton>
            <CButton color="primary" @click="goBack">返回</CButton>
          </Form>
        </CCardBody>
      </CCard>
    </CCol>
  </CRow>
</template>

script部分

<script>
import axios from 'axios';
import Vue from 'vue';
import CKEditor from 'ckeditor4-vue';
import Swal from "sweetalert2";
// 引入vee-validate组件和规则
import { Form, Field, defineRule } from 'vee-validate'
import { required } from '@vee-validate/rules'

// 注册必填校验规则,自定义中文提示
defineRule('required', (value) => {
  if (!value || (typeof value === 'string' && !value.trim()) || value === null) {
    return '该字段为必填项'
  }
  return true
})

Vue.use(CKEditor);

export default {
  name: 'EditUser',
  // 注册vee-validate组件
  components: {
    Form,
    Field
  },
  props: {
    caption: {
      type: String,
      default: '用户id'
    },
  },
  data: () => {
    return {
      note: {
        title: '',
        content: '',
        applies_to_date: '',
        status_id: null,
        note_type: '',
      },
      statuses: [],
      message: '',
      dismissSecs: 7,
      dismissCountDown: 0,
      showDismissibleAlert: false,

      editorData: '',
      editorConfig: {
        // 编辑器配置
        filebrowserImageBrowseUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager?token=' + localStorage.getItem("api_token"),
        filebrowserImageUploadUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager/upload?type=Images&amp;_token=&token=' + localStorage.getItem("api_token"),
        filebrowserBrowseUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager?type=Files&token=' + localStorage.getItem("api_token"),
        filebrowserUploadUrl: Vue.prototype.$apiAdress+'/api/laravel-filemanager/upload?type=Files&amp;_token=&token=' + localStorage.getItem("api_token"),
        height: 500,
        language: 'pl',
        //extraPlugins: 'facebookvideo, youtube, html5video',
        editorUrl: "facebookvideo.js",
        extraPlugins: 'a11yhelp,about,basicstyles,bidi,blockquote,clipboard,colorbutton,colordialog,contextmenu,copyformatting,dialogadvtab,div,editorplaceholder,elementspath,enterkey,entities,exportpdf,filebrowser,find,flash,floatingspace,font,format,forms,horizontalrule,htmlwriter,iframe,image,indentblock,indentlist,justify,language,link,list,liststyle,magicline,maximize,newpage,pagebreak,pastefromgdocs,pastefromlibreoffice,pastefromword,pastetext,preview,print,removeformat,resize,save,scayt,selectall,showblocks,showborders,smiley,sourcearea,specialchar,stylescombo,tab,table,tableselection,tabletools,templates,toolbar,undo,uploadimage, wysiwygarea,autoembed,image2,embedsemantic',
        image2_alignClasses: ['image-align-left', 'image-align-center', 'image-align-right'],
        image2_disableResizer: true,
      }
    }
  },
  methods: {
    goBack() {
      this.$router.go(-1)
    },
    // 校验通过后才会执行该提交方法,无需再手动校验
    store() {
      let self = this;
      axios.post(this.$apiAdress + '/api/notes?token=' + localStorage.getItem("api_token"),
        self.note
      )
        .then(function (response) {
          self.note = {
            title: '',
            content: '',
            applies_to_date: '',
            status_id: null,
            note_type: '',
          };
          self.message = '笔记创建成功。';
          self.showAlert();
        }).catch(function (error) {
        if (error.response.data.message == 'The given data was invalid.') {
          self.message = '';
          for (let key in error.response.data.errors) {
            if (error.response.data.errors.hasOwnProperty(key)) {
              self.message += error.response.data.errors[key][0] + '  ';
            }
          }
          self.showAlert();
        } else {
          console.log(error);
          self.$router.push({path: 'login'});
        }
      });
    },
    countDownChanged(dismissCountDown) {
      this.dismissCountDown = dismissCountDown
    },
    showAlert() {
      this.dismissCountDown = this.dismissSecs
    },
  },
  mounted: function () {
    let self = this;
    axios.get(this.$apiAdress + '/api/notes/create?token=' + localStorage.getItem("api_token"))
      .then(function (response) {
        self.statuses = response.data;
      }).catch(function (error) {
      console.log(error);
      self.$router.push({path: 'login'});
    });
  }
}
</script>

核心改动说明

  • 所有表单元素用Form组件包裹,通过v-slot获取校验错误信息和提交处理方法
  • 原有CInput、CSelect组件通过Field的as属性绑定,每个字段设置唯一name属性和对应的校验规则
  • 移除原有的手动校验逻辑checkInputs,提交时Form会自动触发所有字段的校验,校验通过才会执行提交逻辑
  • 每个字段下方添加错误提示区域,校验不通过时展示对应提示

内容的提问来源于stack exchange,提问作者tarafikttes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 13:24:08