进行网站建设视频教程,苏州诗华洛网站建设,WordPress快速发布文章,石家庄移动端网站建设使用场景
在一些form表单填写内容的时候#xff0c;要限制输入的内容必须是数值、浮点型#xff0c;本来el-input-number就可以实现#xff0c;但是它本身带那个数值控制操作#xff0c;等一系列感觉不舒服的地方。如果只是使用el-input该多好#xff0c;只要监听一下输入…使用场景
在一些form表单填写内容的时候要限制输入的内容必须是数值、浮点型本来el-input-number就可以实现但是它本身带那个数值控制操作等一系列感觉不舒服的地方。如果只是使用el-input该多好只要监听一下输入的内容就好了。于是就可以考虑使用注册指令的方式限制输入的内容。
因为只是限制数值和浮点型数值挺好的限制浮点类型最好是可以传入参数限制具体多少位数。
版本环境
vue的版本是^2.6.12elementui的版本是^2.15.6使用到Vue.directive()方法浏览器的requestAnimationFrame方法、cancelAnimationFrame方法文档对象document的execCommand方法。
文件位置
与index.js同级的文件夹中。src/directive/input.js
引入方式
在入口文件内引用
import App from ./Appimport /directive/input.js// 省略其他new Vue({el: #app,router,store,render: h h(App)
})
复制功能实现
Vue.directive(copy, {bind(el) {el.$value el.innerTextel.handler () {const textarea document.createElement(textarea)textarea.readOnly readonlytextarea.style.position absolutetextarea.style.left -9999pxtextarea.value el.innerText.trim()document.body.appendChild(textarea)textarea.select()const result document.execCommand(Copy)if (result) {Message.success(复制成功)}document.body.removeChild(textarea)}el.addEventListener(click, el.handler)},unbind(el) {el.removeEventListener(click, el.handler)}
})
注册指令过程中有几个钩子函数 实现原理就是为指令绑定的组件设置一个点击事件在销毁的时候注销掉那个点击事件。
在dom文档流中添加一个textarea文本域然后设置一系列的样式使其不会出现在视图窗口中为它赋值将其添加到文档流中然后选中整个文本域的内容。然后调用文档流的document.execCommand(Copy)方法将文本内容复制出来。
这个复制内容功能做的比较简单因为复制出来的内容是取的元素的innerText的所以最好是在那种span标签使用这个指令。
使用方式
div classpage-head-textspan订单编号/spanel-tooltip content复制单号 typelightspan v-copy classpointer stylecolor: #1890ff{{ form.orderSn }}/span/el-tooltip
/div
限制整数浮点数的输入
因为是限制输入类型因此对于绑定的元素需要进行判断判断是否是一个Input类型。如果不是的话就直接通过querySelector去寻找input标签。
需要给指令传递参数用来区分是想进行整数限制还是浮点数限制。需要注意的是这个参数和赋值是两个概念。
v-filter:int 其中的int是一个参数让我们知道这个输入框限制的是整数。
v-filter:decimals 其中的decimals也是一个参数让我们知道这个输入框限制的是浮点数。如果我们想设置这个浮点数最多两位呢在组件里面要怎么用
这就是参数和赋值的区别。以限制两位浮点数为例
v-filter:decimals2
在钩子函数的四个参数之一binding对象中value对应的是2arg对应的是decimals
Vue.directive(filter, {bind(el, binding) {if (el.tagName.toLowerCase() ! input) {el el instanceof HTMLInputElement ? el : el.querySelector(input)}switch (binding.arg) {case int:intFilter(el)breakcase decimals:let decimalsFilterO new DecimalsBinding()decimalsFilterO.decimalsFilter(el, binding)break}},unbind(el, binding) {// 解除事件监听switch (binding.arg) {case int:el.removeEventListener(input, intFilterEx, true)breakcase decimals:el.removeEventListener(input, decimalsFilterEx, true)breakdefault:break}}
})
整数限制
其中intFilter实现
const intFilter function (el) {el.addEventListener(input, intFilterEx, true)
}
const intFilterEx e {e.target.removeEventListener(input, intFilterEx, true)let stop requestAnimationFrame(() {let num e.target.value.replace(/\D/g, ).replace(., )e.target.value e.target.value num.replace(/^0([0-9])/g, $1) || 0e.target.dispatchEvent(new Event(input))e.target.addEventListener(input, intFilterEx, true)window.cancelAnimationFrame(stop)}, 1)
}requestAnimationFrame是浏览器的一个事件在mdn中有详细的解释
https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame 浮点数限制
function decimalsFilterEx(e) {e.target.removeEventListener(input, this.decimalsFilterEx, true)let re new RegExp(^\\D*([0-9]\\d*\\.?\\d{0,${this.decimalsBinding.value}})?.*$)let stop requestAnimationFrame(() {e.target.value e.target.value.replace(re, $1).replace(/^0([0-9])/g, $1)e.target.dispatchEvent(new Event(input))e.target.addEventListener(input, this.decimalsFilterEx, true)window.cancelAnimationFrame(stop)}, 1)
}
class DecimalsBinding {decimalsBinding {}decimalsFilter function (el, binding) {this.decimalsBinding bindingel.addEventListener(input, this.decimalsFilterEx, true)}decimalsFilterEx decimalsFilterEx.bind(this)
}
实现方式 第一步创建一个对象DecimalsBinding对象有三个属性。decimalsBinding用来存储钩子函数中的binding值信息decimalsFilter用来设置对象存储的binging值以及为el添加input事件监听decimalsFilterEx是事件的执行内容。
这里有一些绕因为在整个input.js文件中定义了一个decimalsFilterEx函数方法。而且DecimalsBinding里面也有一个同名的属性。
在new DecimalsBinding()创建实例的时候对象的decimalsFilterEx与input.js文件中的decimalsFilterEx是同一个因为bind方法改变了外围的decimalsFilterEx的this指向。此时decimalsFilterEx里面的this指向的是实体类
第二步 decimalsFilter为输入框绑定input事件在这个事件中先移除原先绑定的监听事件设定正则校验拿到输入框的值使用replace替换里面的值。
然后重新绑定input事件
requestAnimationFrame是一个异步方法像setTimeOut一样会返回一个ID值用来清除这个执行。
requestAnimationFrame的刷新频率和浏览器的渲染频率一样。因此几乎是无感限制。其他监听方法会有几帧显示输入的内容然后立马消失。这种方法会让用户体验更好一点。
最后就是cancelAnimationFrame方法清除这个渲染。因为是嵌套设置如果不清除的话就像是在setInterval里面再次调用setInterval一样。 完整文件代码
import { Message } from element-ui
import Vue from vueconst intFilter function (el) {el.addEventListener(input, intFilterEx, true)
}
const intFilterEx e {e.target.removeEventListener(input, intFilterEx, true)let stop requestAnimationFrame(() {let num e.target.value.replace(/\D/g, ).replace(., )e.target.value e.target.value num.replace(/^0([0-9])/g, $1) || 0e.target.dispatchEvent(new Event(input))e.target.addEventListener(input, intFilterEx, true)window.cancelAnimationFrame(stop)}, 1)
}function decimalsFilterEx(e) {e.target.removeEventListener(input, this.decimalsFilterEx, true)let re new RegExp(^\\D*([0-9]\\d*\\.?\\d{0,${this.decimalsBinding.value}})?.*$)let stop requestAnimationFrame(() {e.target.value e.target.value.replace(re, $1).replace(/^0([0-9])/g, $1)e.target.dispatchEvent(new Event(input))e.target.addEventListener(input, this.decimalsFilterEx, true)window.cancelAnimationFrame(stop)}, 1)
}
class DecimalsBinding {decimalsBinding {}decimalsFilter function (el, binding) {this.decimalsBinding bindingel.addEventListener(input, this.decimalsFilterEx, true)}decimalsFilterEx decimalsFilterEx.bind(this)
}Vue.directive(copy, {bind(el) {el.$value el.innerTextel.handler () {const textarea document.createElement(textarea)textarea.readOnly readonlytextarea.style.position absolutetextarea.style.left -9999pxtextarea.value el.innerText.trim()document.body.appendChild(textarea)textarea.select()const result document.execCommand(Copy)if (result) {Message.success(复制成功)}document.body.removeChild(textarea)}el.addEventListener(click, el.handler)},unbind(el) {el.removeEventListener(click, el.handler)}
})Vue.directive(filter, {bind(el, binding) {if (el.tagName.toLowerCase() ! input) {el el instanceof HTMLInputElement ? el : el.querySelector(input)}switch (binding.arg) {case int:intFilter(el)breakcase decimals:let decimalsFilterO new DecimalsBinding()decimalsFilterO.decimalsFilter(el, binding)break}},unbind(el, binding) {// 解除事件监听switch (binding.arg) {case int:el.removeEventListener(input, intFilterEx, true)breakcase decimals:el.removeEventListener(input, decimalsFilterEx, true)breakdefault:break}}
})export default Vue