美文网首页
vue+element 表单处理显示隐藏的时候 都必填,提交报错

vue+element 表单处理显示隐藏的时候 都必填,提交报错

作者: 黎明的叶子 | 来源:发表于2021-09-08 18:07 被阅读0次

原因是:显示隐藏用的v-show。如果用v-if则不会有这个问题。

1.v-show 和 v-if的区别

v-show 是会渲染到页面上的,只是加了style="display:none";
v-if 不会渲染到页面上。
他们的用法,建议的是如果切换频繁则用v-show。这样可以省去每次的渲染时间。 而如果渲染后则不再频繁改变,这种用v-if ,这样省去多余的渲染元素,没必要的不会渲染页面。
然而以表单为例,则是特殊的。因为这种显示隐藏,也可能会频繁切换,按照理解为觉得应该用v-show。可是用了v-show,页面会渲染出内容,只是不显示。这种情况,用element的提交,则通过display:none的隐藏也会被判断,所以会报错。这个时候用v-if 更合理。不过这里得了解element的工作方式。
我觉得大多数时候都应该用v-if,比如权限按钮判断的时候,不能把没有权限的HTML暴露在网页中,如果只是静态的文本内容,显示隐藏我觉得可以用v-show。

2.element和vue的关系,代码中如何体现

好奇的问题,element为什么能够被vue使用?如何加载到Vue中的?
其实element跟我们自己写的公共组件一样,它就是我们用的组件,只是被加载到了我们的项目中,加载到Vue对象下。就可以使用了。
先说下,如何找到源码以Form表单为例,element的源码在node_modules下,找到element-ui文件夹。里面包含的lib文件夹是打包后让我们调用的,packages里面是源码。入口是src/index.js,如下图

image.png
如果看源码的话,可以从packages里面找到form文件夹。里面的index.js 是入口,其他对应的是组件的内容。组件的原理跟我们自己写的button.vue组件是一样的。
image.png
如果看不懂,要调试,可以从lib下找到form.js。直接加debugger调试,一步步看流程。

再说下vue的大体机制,vue的组件,要知道都是一个VueComponent对象,这个对象继承Vue对象,再继承Object对象。vue 组件的内在关系为最外层的是个组件,里面如果用到子组件,那么就一层层嵌套。会绑定在对象的children对象上。如果当前页面有组件加ref,那么这个组件则会通过$ref直接绑定到根组件上。需要注意的是这个children和ref里面放的都是VueComponent(组件对应的对象),举个例子

image.png
image.png
所以vue 把element组件加载后,也是加载在自己的对象下。

最后他们连接在了一起
如果我们是单独引入,我们会在vue的入口main.js中引入组件。用

improt Form,FormItem from 'element-ui';
Vue.use(Form);
Vue.use(FormItem);

对应的Form的入口是


image.png

(这里省略一步是Form对应的ELForm。是最外层的入口里面导入的)
Vue.use(Form) 执行的逻辑是,找到Form里面的install。然后把Vue 传递给里面。可以理解为这样调用Form.install(this)。看如上代码,会把这个Form 通过Vue.component 注入到vue中。这样就可以在自己的页面用element组件的方法了。如:

//this.$refs["formInline"] 访问到了这个VueComponent对象, 然后找到对应的方法
this.$refs["formInline"].validate((valid) => {
        if (valid) {
          console.log(this.formInline);
          console.log("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });

3.element提交判断的逻辑

这里介绍的就是validate方法了。回到element的源码。就是这个form.js里面的validate方法。(form.js是打包后的,对应的是form.vue)沿着这个方法一步步看逻辑即可

// form 里面的
validate: function validate(callback) { 
      var _this2 = this; 
      // 先进行一些极端情况的判断
      // this.model 指的就是绑定的数据。如果没有绑定数据,则给出警告。
      if (!this.model) {
        console.warn('[Element Warn][Form]model is required for validate to work!');
        return;
      }

      var promise = void 0;
      // if no callback, return promise
      if (typeof callback !== 'function' && window.Promise) {
        promise = new window.Promise(function (resolve, reject) {
          callback = function callback(valid) {
            valid ? resolve(valid) : reject(valid);
          };
        });
      }

      var valid = true;
      var count = 0;
      // 如果需要验证的fields为空,调用验证时立刻返回callback
      if (this.fields.length === 0 && callback) {
        callback(true);
      }
     // this.fields是在created里面通过注册事件一个一个添加进来的。
     // 它代表的是页面里面有prop的el-form-item。
     // 这里可以看出,如果用v-show。那么就能获取这个fields。那么下面的循环就会判断当前的字段。
     // 所以就会出现,我之前的问题。虽然隐藏了,但是还是会判断。如果用v-if则不会到fields里面,所以数据的rules如何定义并不影响。
    
    // 如果该有的数据都有,那么进入核心代码。
      var invalidFields = {};
      // debugger
      this.fields.forEach(function (field) {
        // 这里每一个field 其实就是el-form-item 这个子组件。里面也有对应的validate方法。这里调用的子组件的方法。
        // ————> 指向下面的validate方法
        field.validate('', function (message, field) {
          if (message) {
            valid = false;
          }
          // 合并对象到invalidFields
          invalidFields = merge_default()({}, invalidFields, field);
          if (typeof callback === 'function' && ++count === _this2.fields.length) {
            callback(valid, invalidFields);
          }
        });
      });

      if (promise) {
        return promise;
      }
    },

这里我们可以从form-item.vue(跟打包后的js里面的是一样的)里面看验证的方法,如下

// form-item 里面的
 validate(trigger, callback = noop) {
        this.validateDisabled = false;
        // 这里会获取el-form组件里面定义的rules 和 el-form-item上定义的rule。然后合并他们。所以rules 就是应用到这个item上的规则。
        // 基础数据的判断
        const rules = this.getFilteredRule(trigger);
        if ((!rules || rules.length === 0) && this.required === undefined) {
          callback();
          return true;
        }

        this.validateState = 'validating';
        
        // 验证逻辑 添加样式 往下的没细看了
        const descriptor = {};
        if (rules && rules.length > 0) {
          rules.forEach(rule => {
            delete rule.trigger;
          });
        }
        descriptor[this.prop] = rules;

        const validator = new AsyncValidator(descriptor);
        const model = {};

        model[this.prop] = this.fieldValue;

        validator.validate(model, { firstFields: true }, (errors, invalidFields) => {
          this.validateState = !errors ? 'success' : 'error';
          this.validateMessage = errors ? errors[0].message : '';

          callback(this.validateMessage, invalidFields);
          this.elForm && this.elForm.$emit('validate', this.prop, !errors, this.validateMessage || null);
        });
      },

这里延展一个问题。就是v-show 的时候虽然fields里面有了,但是我们是否可以改变rules,然后让其通过验证。是可以的。虽然不是最好的方法。但是是可以的。要注意改变的时机,是否需要用nextTick。

4. 表单到底应不应该拆分组件

只是个人看法而已。
我觉得如果表单数据比较多。显示隐藏的块比较大。则应该把独立的块作为组件。传数据的话,直接传formInline即可。
另一种公共的肯定要拆出来。

相关文章

  • type=hidden隐藏域有什么作用? 举例说明

    隐藏域中可以存储表单数据,但是对访问者不可见。提交表单时,隐藏域中的内容也会被提交给服务器进行处理, 隐藏的数据通...

  • 8.页面无刷新操作

    思路:通过两个隐藏的表单实现,隐藏的A表单点击按钮显示,onclick()监听提交到服务器。通过target返回到...

  • form表单验证

    表单验证分类: 1、必填性:可以利用原生的表单元素的自身属性,required ;当采用表单原生的提交(非Ajax...

  • CSRF verification failed. Reques

    Django版本:2.0.1 遇到的问题,在提交表单的时候,系统报错: Forbidden (403) CSRF ...

  • form表单提交

    今天学了一个form表单的提交 php中的一些处理 中途的报错://Call to undefined metho...

  • SpringMVC+Thymeleaf 处理表单提交

    SpringMVC+Thymeleaf 处理表单提交 thymleaf处理表单提交的方式和jsp有些类似,也有点不...

  • SpringMVC+Thymeleaf 处理表单提交

    SpringMVC+Thymeleaf 处理表单提交 thymleaf处理表单提交的方式和jsp有些类似,也有点不...

  • 关于form表单

    关于form表单的几种提交方式 1.隐藏form提交,更新数据完成后,需要转到一个空白页面再对原页面进行提交后处理...

  • antd from表单

    antd from表单简介及必填校验使用 一、功能 具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框...

  • HTML表单

    表单基础结构 表单语法 标签 单行文本域 按钮 图像域和隐藏域 图像域(图像提交按钮) 隐藏域 隐藏域的内容用户看...

网友评论

      本文标题:vue+element 表单处理显示隐藏的时候 都必填,提交报错

      本文链接:https://www.haomeiwen.com/subject/rbiiwltx.html