前言

很久没有写文章了,学习了一下webpack,基础的一些组件,今天带来form表单验证组件(element.iviewui)的一期教程(作为一个菜鸡毕竟经历众多项目可以给一些新手一点提示 (QQ群技术讨论)838293023备注(github进来的

github 技术文档 技术文档会持续更新

效果图

vue表单验证你真的会了吗?vue表单验证(form)validate 

1.原理解释

vue表单验证你真的会了吗?vue表单验证(form)validate

考虑

我们看一下我们可以用form去整体触发校验也可以单个input来触发form-item 进行校验 童鞋们现在可能感觉还是没懂,没关系继续往下看。

2.派发和广播

为什么要用广播和派发呢。通常我们和业务没有关系的组件尽量不要使用vuex和bus(事件总线)。 下面我送上广播和派发的代码。我们在需要调用组件绑上 this.$on('event',res=>()) ,通过派发和广播进行调用 $emit

  • 派发是向上查找且只调用1个
  • 广播是向下查找调用多个
  • 注意"htmlcode">
    emitter.js
    /**
     * 递归使用 call 方式this指向
     * @param componentName // 需要找的组件的名称
     * @param eventName // 事件名称
     * @param params // 需要传递的参数
     */
    function broadcast(componentName, eventName, params) {
     // 循环子节点找到名称一样的子节点 否则 递归 当前子节点
     this.$children.map(child=>{
      if (componentName===child.$options.name) {
       child.$emit.apply(child,[eventName].concat(params))
      }else {
       broadcast.apply(child,[componentName,eventName].concat(params))
      }
     })
    }
    export default {
     methods: {
      /**
       * 派发 (向上查找) (一个)
       * @param componentName // 需要找的组件的名称
       * @param eventName // 事件名称
       * @param params // 需要传递的参数
       */
      dispatch(componentName, eventName, params) {
       let parent = this.$parent || this.$root;//$parent 找到最近的父节点 $root 根节点
       let name = parent.$options.name; // 获取当前组件实例的name
       // 如果当前有节点 && 当前没名称 且 当前名称等于需要传进来的名称的时候就去查找当前的节点
       // 循环出当前名称的一样的组件实例
       while (parent && (!name||name!==componentName)) {
        parent = parent.$parent;
        if (parent) {
         name = parent.$options.name;
        }
       }
       // 有节点表示当前找到了name一样的实例
       if (parent) {
        parent.$emit.apply(parent,[eventName].concat(params))
       }
      },
      /**
       * 广播 (向下查找) (广播多个)
       * @param componentName // 需要找的组件的名称
       * @param eventName // 事件名称
       * @param params // 需要传递的参数
       */
      broadcast(componentName, eventName, params) {
       broadcast.call(this,componentName, eventName, params)
      }
     }
    }

    3.async-validator

    不懂 async-validator 可以去官网看看 github

    yarn add async-validator // 因为当前这个插件是需要打包到项目里的所以不能加-D

    4.api设计

    我们看一下下面 element 官网的图`

    form 有2个注入的字段 :rules 规则,和 :model 当前form的值会通过 model 的值和 rules 进行匹配来进行校验.

    form-item 有2个注入的字段 lableprop ( prop )是来和 form 进行匹配来获取当前的 form-item 的值的

    input 其实有当前的 @input 的方法。 v-model 就不解释了

    vue表单验证你真的会了吗?vue表单验证(form)validate 

    form

    我们在 form 先开始注入当前所有的 form-item 实例(获取)

    created 会在生命周期开始的时候绑定和删除当前实例的方法。通常绑定都在页面dom开始前调用需要在 dom 加载完

    provide 配合inject 使用让子组件可以调用当前父组件的方法以及data

    下面都写了备注可以放心食用(经过测试当前是可以进行校验的)

    form.vue
    <template>
     <form>
      <slot></slot>
     </form>
    </template>
    
    <script>
     export default {
      name: "aiForm",
      provide(){ // [不懂的可以看看](https://cn.vuejs.org/v2/api/#provide-inject)
       return {
        form: this
       }
      },
      props: {
       // 当前 form 的model
       model: {
        type: Object
       },
       // 验证
       rules: {
        type: Object
       }
      },
      data(){
       return{
        fields: [] // 储存当前的 form-item的实例
       }
      },
      created(){
       // 存当前实例
       let that =this;
       this.$on('on-form-item-add',item=>{
        if (item) {
         that.fields.push(item)
        }
       });
       // 删除当前有的实例
       this.$on('on-form-item-remove',item=>{
        if (item.prop) {// 如果当前没有prop的话表示当前不要进行删除(因为没有注入)
         that.fields.splice(that.fields.indexOf(item),1)
        }
       })
      },
      methods:{
       /**
        * 清空
        */
       resetFields(){//添加resetFields方法使用的时候调用即可
        /**
         * 当前所有当form-item 进行赋值
         */
        this.fields.forEach(field => {
         field.resetField();
        });
       },
       /**
        * 校验 公开方法:全部校验数据,支持 Promise
        */
       validate(callback){
        return new Promise(resolve=>{
         /**
          * 当前所有当form-item 进行校验
          */
         let valid = true; // 默认是通过
         let count = 0; // 来匹配当前是否是全部检查完
         this.fields.forEach(field => {
          // 每个实例都会有 validation 的校验的方法
          field.validation('',error=>{
           // 只要有一个不符合那么当前的校验就是未通过的
           if (error) { 
            valid = false;
           }
           // 通过当前检查完所有的form-item的时候才会调用
           if (++count === this.fields.length) {
            resolve(valid);// 方法使用then
            if (typeof callback === 'function') {
             callback(valid);// 直接调用注入的回调方法
            }
           }
          });
         });
        })
       }
      }
     }
    </script>

    5.form-item

    •  form-item比较复杂我们一个一个讲
    • isRequired来判断当前是否需要必填
    • validateState来判断当前校验的状态
    • validateMessage当前的错误的值
    • inject: ['form'] 我们就可以通过this.from.xxx来调用父组件的事件以及值了
    • computed下的fieldValue可能在不停的变化所以我们通过计算属性来使用
    • initialValue 默认的值我们在mounted的时候且当前需要进行校验的时候(prop有的时候)会赋值
    • mixins: [Emitter]混合器就是里面的方法以及date都可以在当前调用使用频繁的都可以放在混合器里面
    • 我们form-item 会传入input的两个方法blur和change(input原生使用的@input)通过form传入的校验rules里面的trigger来判断
    form-item.vue
    <template>
     <div>
      <label :class="isRequired">{{label}}</label>
      <div>
       <slot></slot>
       <div class="ai-form-item-message" v-if="validateState==='error'">{{validateMessage}}</div>
      </div>
     </div>
    </template>
    
    <script>
     import Emitter from '../../mixins/emitter';
     import schema from 'async-validator';
     export default {
      name: "aiFormItem",
      mixins: [Emitter],
      inject: ['form'],
      props: {
       label: {
        type: String,
        default: ''
       },
       prop:{
        type: String
       },
      },
      computed:{
       fieldValue () {
        return this.form.model[this.prop];
       },
      },
      data(){
       return {
        initialValue: '', // 储存默认值
        isRequired: false, // 当前的是否有问题
        validateState: '', // 是否校验成功
        validateMessage: '', // 校验失败文案
       }
      },
      methods:{
       /**
        * 绑定事件 进行是否 required 校验
        */
       setRules(){
        let that = this;
        let rules = this.getRules();//拿到父组件过滤后当前需要使用的规则
        if (rules.length) {
         // every 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)
         // some 只要有一个符合就返回true
         this.isRequired = rules.some(rule=>{
          // 如果当前校验规则中有必填项,则标记出来
          return rule.required;
         })
        }
        /**
         * blur 事件
         */
        this.$on('on-form-blur',that.onFieldBlur);
        /**
         * change 事件
         */
        this.$on('on-form-change',that.onFieldChange)
       },
       /**
        * 从 Form 的 rules 属性中,获取当前 FormItem 的校验规则
        */
       getRules () {
        let that = this;
        let rules = that.form.rules;
        rules = rules"color: #ff0000">5.input

    •  value 支持一个入参
    • 因为当前是一个 input 注入的参数是不能直接放到 input 里面使用的所以先赋值给了 defaultValue 然后用 watch 来不停给 defaultValue 赋值达到一个父组件修改后的一个绑定
    <template>
     <input type="text"
       @input="handleInput" // change
       @blur="handleBlur"
       :value="defaultValue"
     >
    </template>
    
    <script>
     import Emitter from '../../mixins/emitter.js'
     export default {
      name: "aiInput",
      mixins: [Emitter],
      props: {
       value: {
        type: String,
        default: ''
       }
      },
      data(){
       return {
        defaultValue: this.value
       } 
      },
      watch:{
       value (val) {
        this.defaultValue = val;
       }
      },
      methods:{
       /**
       * change 事件
       * @param event
       */
       handleInput(event){
        // 当前model 赋值
        this.defaultValue = event.target.value;
        // vue 原生的方法 return 出去
        this.$emit('input',event.target.value);
        // 将当前的值发送到 aiFormItem 进行校验
        this.dispatch('aiFormItem','on-form-change',event.target.value)
       },
       /**
       * blur 事件
       * @param event
       */
       handleBlur(event){
        // vue 原生的方法 return 出去
        this.$emit('blur',event.target.value);
        // 将当前的值发送到 aiFormItem 进行校验
        this.dispatch('aiFormItem','on-form-blur',event.target.value)
       }
      }
     }
    </script>

    最后

    最后给上一个当前可以的使用方式

    <template>
     <div class="home">
     <button @click="changeButton">测试</button>
     <ai-form ref="formItems" :model="formValidate" :rules="ruleValidate">
      <ai-form-item label="用户名" prop="name">
      <ai-input v-model="formValidate.name"/>
      </ai-form-item>
     </ai-form>
     </div>
    </template>
    
    <script>
     import AiForm from "../components/form/form";
     import AiFormItem from "../components/form/form-item";
     import AiInput from "../components/input/ai-input";
    export default {
     name: 'home',
     components: {AiInput, AiFormItem, AiForm},],
     data(){
      return{
       formValidate: {
        name: '123z',
        mail: ''
       },
       ruleValidate: {
        name: [
         { required: true, message: '用户名不能为空', trigger: 'blur' },
        ],
       }
      }
     },
     methods:{
      changeButton(){
       this.$refs.formItems.resetFields() // 清空方法
       this.$refs.formItems.validate() // 验证方法
        .then(res=>{
         console.log(res)
        })
      }
     },
    }
    </script>

    小结

    可能现在小伙伴还是不懂。。俗话说;师傅领进门,修行在个人。代码上的备注写的也够多了。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?