注册全局指令(表单验证)
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 }
;
一辈子很短,努力的做好两件事就好;第一件事是热爱生活,好好的去爱身边的人;第二件事是努力学习,在工作中取得不一样的成绩,实现自己的价值,而不是仅仅为了赚钱;