设计网站高级感,游戏开发物语完美搭配,企业网站设计服务公司,上海高档网站建设Vue 有一些很实用的指令 v-show v-if v-text v-html v-bind v-on 可以帮助我们实现很复杂的功能#xff0c;同时它还开辟了钩子供我们自己实现自定义指令。根据自己平时开发总结了一些可以通过指令实现的功能场景#xff1a;控制页面元素显示与隐藏#xff0c;可用作控制权限… Vue 有一些很实用的指令 v-show v-if v-text v-html v-bind v-on 可以帮助我们实现很复杂的功能同时它还开辟了钩子供我们自己实现自定义指令。根据自己平时开发总结了一些可以通过指令实现的功能场景控制页面元素显示与隐藏可用作控制权限功能页面元素点击事件防抖与节流通过自定义指令控制图片懒加载针对页面特定元素添加自定义行为对输入内容进行过滤下面列举一些常见的自定义指令的实现代码权限指令/*** 权限指令 * param {string} value 权限标识* 例div v-permissioneditInfo/div*/
Vue.directive(permission, {inserted: function (el, binding) {const { value } binding// 在前置路由拦截获取权限按钮列表后存储在 store 中const actionList store.state.user.permissionif (value) {const hasPermission actionList .some(btnKey btnKey value)// 没有权限直接移除 dom元素if (!hasPermission) {el.parentNode el.parentNode.removeChild(el)}} else {throw new Error(需要指定权限标识 如v-permissioneditInfo)}}
})防抖指令/*** 防抖指令 单位时间只触发最后一次* param {Function} fn - 执行事件* param {?String|click} event - 事件类型 例click* param {?Number|500} time - 间隔时间* param {Array} binding.value - [fn,event,time]* 直接使用 XXX v-debouncereset]刷新/XXX* 配置事件间隔时间 button v-debounce[reset,click,500]刷新/button* 事件传递参数则 button v-debounce[()reset(param),click,500]刷新/button*/
Vue.directive(debounce, {bind: function (el, binding) {try {let fn, event click, time 500;if (typeof binding.value function) {fn binding.value} else {[fn, event click, time 500] binding.value}let timer;el.addEventListener(event, () {timer clearTimeout(timer)timer setTimeout(() fn(), time)})} catch (e) {console.log(e)}}
})节流指令/*** 节流指令 一段时间内首次触发时立即执行此时间段内再次触发不会执行* param {Function} fn - 执行事件* param {?String|click} event - 事件类型 例click* param {?Number|500} time - 间隔时间* param {Array} binding.value - [fn,event,time]* 直接使用 XXX v-throttlereset]刷新/XXX* 配置事件间隔时间 button v-throttle[reset,click,500]刷新/button* 事件传递参数则 button v-throttle[()reset(param),click,500]刷新/button*/
Vue.directive(throttle, {bind: function (el, binding) {let fn, event click, time 1500;if (typeof binding.value function) {fn binding.value} else {[fn, event click, time 1500] binding.value}/*** el.preTime 记录上次触发事件* 每次触发比较nowTime当前时间 和 el.preTime 的差是否大于指定的时间段*/el.addEventListener(event, () {const nowTime new Date().getTime()if (!el.preTime || nowTime - el.preTime time) {el.preTime nowTimefn();}})}
})图片懒加载Vue.directive(lazy, {bind(el, binding) {LazyLoad.init(el, binding.value, defaultSrc)},inserted(el) {if (IntersectionObserver) {LazyLoad.observe(el)} else {LazyLoad.listenerScroll(el)}},
})
// 初始化
init(el, val, def) {el.setAttribute(data-src, val)el.setAttribute(src, def)
},
// 利用IntersectionObserver监听el
observe(el) {var io new IntersectionObserver((entries) {const realSrc el.dataset.srcif (entries[0].isIntersecting) {if (realSrc) {el.src realSrcel.removeAttribute(data-src)}}})io.observe(el)
},
// 监听scroll事件
listenerScroll(el) {const handler LazyLoad.throttle(LazyLoad.load, 300)LazyLoad.load(el)window.addEventListener(scroll, () {handler(el)})
}给块元素增加背景/**
* 使用 canvas 特性生成 base64 格式的图片文件设置其字体大小颜色等。
* 将其设置为背景图片从而实现页面或组件水印效果
**/
Vue.directive(waterMarker, {bind: function (el, binding) {addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor)}
}),
addWaterMarker(str, parentNode, font, textColor) {// 水印文字父元素字体文字颜色var can document.createElement(canvas)parentNode.appendChild(can)can.width 200can.height 150can.style.display nonevar cans can.getContext(2d)cans.rotate((-20 * Math.PI) / 180)cans.font font || 16px Microsoft JhengHeicans.fillStyle textColor || rgba(180, 180, 180, 0.3)cans.textAlign leftcans.textBaseline Middlecans.fillText(str, can.width / 10, can.height / 2)parentNode.style.backgroundImage url( can.toDataURL(image/png) )
}页面元素拖拽指令/**
* 设置需要拖拽的元素为相对定位其父元素为绝对定位
* 鼠标按下(onmousedown)时记录目标元素当前的 left 和 top 值
* 鼠标移动(onmousemove)时计算每次移动的横向距离和纵向距离的变化值并改变元素的 left 和 top 值
**/
Vue.directive(waterMarker, {inserted: function (el) {el.style.cursor moveel.onmousedown function (e) {let disx e.pageX - el.offsetLeftlet disy e.pageY - el.offsetTopdocument.onmousemove function (e) {let x e.pageX - disxlet y e.pageY - disylet maxX document.body.clientWidth - parseInt(window.getComputedStyle(el).width)let maxY document.body.clientHeight - parseInt(window.getComputedStyle(el).height)if (x 0) {x 0} else if (x maxX) {x maxX}if (y 0) {y 0} else if (y maxY) {y maxY}el.style.left x pxel.style.top y px}document.onmouseup function () {document.onmousemove document.onmouseup null}}},
})输入框过滤特殊字符let findEle (parent, type) {return parent.tagName.toLowerCase() type ? parent : parent.querySelector(type)
}
const trigger (el, type) {const e document.createEvent(HTMLEvents)e.initEvent(type, true, true)el.dispatchEvent(e)
}
Vue.directive(filterInput, {bind: function (el, binding, vnode) {// 正则规则可根据需求自定义var regRule /[^u4E00-u9FA5|d|a-zA-Z|rns,.?!。…—$()-/*{}[]]|s/glet $inp findEle(el, input)el.$inp $inp$inp.handle function () {let val $inp.value$inp.value val.replace(regRule, )trigger($inp, input)}$inp.addEventListener(keyup, $inp.handle)},unbind: function (el) {el.$inp.removeEventListener(keyup, el.$inp.handle)}
})增加长按行为实现长按用户需要按下并按住按钮几秒钟触发相应的事件/**
* 创建一个计时器 2 秒后执行函数
* 当用户按下按钮时触发 mousedown 事件启动计时器用户松开按钮时调用 mouseout 事件。
* 如果 mouseup 事件 2 秒内被触发就清除计时器当作一个普通的点击事件
* 如果计时器没有在 2 秒内清除则判定为一次长按可以执行关联的函数。
* 在移动端要考虑 touchstarttouchend 事件
**/
Vue.directive(longpress, {bind: function (el, binding, vNode) {if (typeof binding.value ! function) {throw callback must be a function}// 定义变量let pressTimer null// 创建计时器 2秒后执行函数 let start (e) {if (e.type click e.button ! 0) {return}if (pressTimer null) {pressTimer setTimeout(() {handler()}, 2000)}}// 取消计时器let cancel (e) {if (pressTimer ! null) {clearTimeout(pressTimer)pressTimer null}}// 运行函数const handler (e) {binding.value(e)}// 添加事件监听器el.addEventListener(mousedown, start)el.addEventListener(touchstart, start)// 取消计时器el.addEventListener(click, cancel)el.addEventListener(mouseout, cancel)el.addEventListener(touchend, cancel)el.addEventListener(touchcancel, cancel)},// 当传进来的值更新的时候触发componentUpdated(el, { value }) {el.$value value},// 指令与元素解绑的时候移除事件绑定unbind(el) {el.removeEventListener(click, el.handler)},
})- END -