• 注册全局指令(表单验证)


    1). 导出验证指令对象

    在 src/directives 下新建 validator.js 文件,复制贴入以下代码:

    src/directives/validator.js

      1 function validate(el, modifiers, bindingValue) {
      2   bindingValue = bindingValue && typeof bindingValue === 'object' ? bindingValue : {}
      3   const value = typeof el.value === 'string' ? el.value.trim() : ''
      4   const { title = '该项', error } = bindingValue
      5   let defaultError = ''
      6 
      7   if (modifiers.required && value === '') {
      8     defaultError = `${title}不能为空`
      9   } else if (bindingValue.target) {
     10     const target = document.querySelector(bindingValue.target)
     11     const targetValue = target ? target.value : null
     12 
     13     if (targetValue !== value) {
     14       defaultError = `输入的${title}不匹配`
     15     }
     16   } else if (bindingValue.regex) {
     17     try {
     18       if (!bindingValue.regex.test(value)) {
     19         defaultError = `${title}格式不正确`
     20       }
     21     } catch (e) {}
     22   }
     23 
     24   if (defaultError) {
     25     if (error === undefined) {
     26       showError(el, defaultError)
     27     } else {
     28       showError(el, error)
     29     }
     30   } else {
     31     showError(el)
     32   }
     33 }
     34 
     35 function showError(el, error) {
     36   const parentElement = el.parentElement
     37   const errorElement = getErrorElement(el)
     38 
     39   if (error === undefined) {
     40     errorElement.style.display = 'none'
     41     parentElement.classList.remove('has-error')
     42   } else {
     43     errorElement.textContent = error
     44     errorElement.style.display = 'block'
     45     parentElement.classList.add('has-error')
     46   }
     47 }
     48 
     49 function getErrorElement(el) {
     50   const parentElement = el.parentElement
     51   let errorElement = parentElement.querySelector('.help-block')
     52 
     53   if (!errorElement) {
     54     const tpl = `<span class="help-block"></span>`
     55     const fragment = document.createRange().createContextualFragment(tpl)
     56 
     57     parentElement.appendChild(fragment)
     58     errorElement = parentElement.querySelector('.help-block')
     59   }
     60 
     61   return errorElement
     62 }
     63 export default {
     64   bind(el, binding, vnode) {
     65     // 使用解构赋值声明 value = binding.value,  arg = binding.arg,  modifiers = binding.modifiers 
     66     const { value, arg, modifiers } = binding
     67     // 如果没传对应的事件名称参数,就默认使用 change 事件
     68     const eventType = ['change', 'blur', 'input'].indexOf(arg) !== -1 ? arg : 'change'
     69     // 默认处理器,当用户开始输入时,移除错误提示
     70     const defaultHandler = () => {
     71       showError(el)
     72     }
     73     // 验证处理器,当用户触发对应的事件时,验证用户输入的信息
     74     const handler = () => {
     75       validate(el, modifiers, value)
     76     }
     77 
     78     // 在 el 元素上的添加 input 事件监听
     79     el.addEventListener('input', defaultHandler, false)
     80     // 在 el 元素上的添加用户指定的事件监听
     81     el.addEventListener(eventType, handler, false)
     82 
     83     // 移除 el 元素上事件监听和数据绑定的方法
     84     el.destroy = () => {
     85       el.removeEventListener('input', defaultHandler, false)
     86       el.removeEventListener(eventType, handler, false)
     87       el.destroy = null
     88     }
     89   },
     90   inserted(el, binding, vnode) {//被绑定插入父节点的时候调用,保证了父节点的存在
     91     const { value, modifiers } = binding
     92     // 指定当前一系列验证项的父级,我们这里指定为含 data-validator-form 的元素
     93     const form = el.closest('[data-validator-form]')
     94     // 指定一个按钮来检查所有验证项,我们这里指定为含 type=submit 的元素
     95     const submitBtn = form ? form.querySelector('[type=submit]') : null
     96 
     97     if (submitBtn) {
     98       // 提交处理器
     99       const submitHandler = () => {
    100         // 验证所有项
    101         validate(el, modifiers, value)
    102 
    103         // 获取错误信息
    104         const errors = form.querySelectorAll('.has-error')
    105 
    106         if (!errors.length) {
    107           // 没有错误信息时,在按钮上添加一个 canSubmit 属性,并指定为 true
    108           submitBtn.canSubmit = true
    109         } else {
    110           // 有错误信息时,在按钮上添加一个 canSubmit 属性,并指定为 false
    111           submitBtn.canSubmit = false
    112         }
    113       }
    114 
    115       // 在按钮上的添加 click 事件监听
    116       submitBtn.addEventListener('click', submitHandler, false)
    117 
    118       // 移除按钮上事件监听和数据绑定的方法
    119       el.destroySubmitBtn = () => {
    120         submitBtn.removeEventListener('click', submitHandler, false)
    121         el.destroySubmitBtn = null
    122       }
    123     }
    124   },
    125   unbind(el) {
    126     // 移除事件监听和数据绑定
    127     el.destroy()
    128     if (el.destroySubmitBtn) el.destroySubmitBtn()
    129   }
    130 }

    2). 注册全局验证指令

    在 src/directives 下新建 index.js 文件,复制贴入以下代码:

    src/directives/index.js

    import Vue from 'vue'
    import validator from './validator'
    
    Vue.directive('validator', validator)

    注册全局指令需要使用 Vue.directive,第一个参数 'validator' 是指令名称,第二个参数 validator 是指令对象或者指令函数,我们这里是指令对象。全局注册的好处是,可以在实例内部的所有组件中使用,而不用在每个组件内部单独引用和注册。

     

    3). 引入全局验证指令

    打开 src/main.js 文件,引入 ./directives

    src/main.js

    1 import Vue from 'vue'
    2 import App from './App'
    3 import router from './router'
    4 import './directives'

    4). 使用表单验证指令

    打开 src/views/auth/Register.vue,查找 <div class="panel-body"> 元素,复制以下代码将其替换:

    src/views/auth/Register.vue

     1 <div class="panel-body" data-validator-form>
     2   <div class="form-group">
     3     <label class="control-label">用户名</label>
     4     <input v-validator:input.required="{ regex: /^[a-zA-Z]+w*s?w*$/, error: '用户名要求以字母开头的单词字符' }" type="text" class="form-control" placeholder="请填写用户名">
     5   </div>
     6   <div class="form-group">
     7     <label class="control-label">密码</label>
     8     <input id="password" v-validator.required="{ regex: /^w{6,16}$/, error: '密码要求 6 ~ 16 个单词字符' }" type="password" class="form-control" placeholder="请填写密码">
     9   </div>
    10   <div class="form-group">
    11     <label class="control-label">确认密码</label>
    12     <input v-validator.required="{ target: '#password' }" type="password" class="form-control" placeholder="请填写确认密码">
    13   </div>
    14   <div class="form-group">
    15     <label class="control-label">图片验证码</label>
    16     <input v-validator.required="{ title: '图片验证码' }" type="text" class="form-control" placeholder="请填写验证码">
    17   </div>
    18   <div class="thumbnail" title="点击图片重新获取验证码">
    19     <div class="captcha"></div>
    20   </div>
    21   <button type="submit" class="btn btn-lg btn-success btn-block">
    22     <i class="fa fa-btn fa-sign-in"></i> 注册
    23   </button>
    24 </div>

    我们先在外层元素上,添加 data-validator-form 属性,使其成为所有验证项的父级:

    1 <div class="panel-body" data-validator-form>

    自定义指令知识:

    • binding.name:指令名,不包括 v- 前缀,这里是 'validator' ;
    • binding.value:指令的绑定值,这里是 { regex: /^[a-zA-Z]+w*s?w*$/, error: '用户名要求以字母开头的单词字符' } ;
    • binding.arg:传给指令的参数,这里是 'input' ;
    • binding.modifiers:一个包含修饰符的对象,这里是 { required: true } ;
  • 相关阅读:
    使用Bootstrap后,关于IE与Chrome显示字体的问题
    利用百度接口,识别身份证
    双日历日期选择控件
    回复一个朋友:如何理解委托
    IIS7增加mine类型,以便可以访问apk
    关于SqlBulkCopy SQL批量导入需要注意,列名是区分大小写的
    关于取表中id最大值+1的select语句,哪种效率更高?
    MySQL中如何分析查询语句
    判断同名股票是否存在的MyBatis查询函数写法
    Thymeleaf中model设一个值 页面显示此值 JS取此值
  • 原文地址:https://www.cnblogs.com/yangguoe/p/9309278.html
Copyright © 2020-2023  润新知