vue实用指令
先批量注册组件指令,新建directives/index.js文件
import copy from './copy'
const directives = {
copy
}
const install = function (Vue) {
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key])
})
}
export default install
在main.js中导入文件
import Vue from 'vue' import Directives from '@/directives/index' Vue.use(Directives)
一、点击复制文本指令
新建directives/copy.js文件
/*
* 实现思路
* 动态创建 textarea 标签,并设置 readOnly 属性及移出可视区域
* 将要复制的值赋给 textarea 标签的 value 属性,并插入到 body
* 选中值 textarea 并复制
* 将 body 中插入的 textarea 移除
* 在第一次调用时绑定事件,在解绑时移除事件
*/
const copy = {
bind(el, binding) {
const value = binding.value
el.$value = value
const abc = () => {
if (!el.$value) {
// 值为空时
console.log('无复制内容!')
return
}
// 动态创建textarea标签
const textarea = document.createElement('textarea')
// 将该textarea设为readonly防止ios下自动唤起键盘,同时将textarea移出可视区域
textarea.readOnly = 'readonly'
textarea.style.position = 'absolute'
textarea.style.left = '-9999px'
// 将要copy的值赋值给textarea标签的value属性
textarea.value = el.$value
// 将textarea插入到body中
document.body.appendChild(textarea)
// 选中值
textarea.select()
// 将选中的值复制并赋值给result
const result = document.execCommand('Copy')
if (result) {
console.log('复制成功!')
}
document.body.removeChild(textarea)
}
// 绑定点击事件
el.addEventListener('click', abc)
},
// 当传进来的值更新的时候触发
componentUpdated(el, { value }) {
el.$value = value
},
// 指令与元素解绑的时候,移除事件绑定
unbind(el) {
el.removeEventListener('click', el.handler)
}
}
export default copy
使用方法,点击p标签就可以实现复制
<template>
<div>
<p v-copy="copyText">复制</p>
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
copyText: 'a copy directives'
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
</style>
二、拖拽指令
新建directives/draggable.js文件
// clientX 以浏览器左上顶角为原点,定位 x 轴坐标 // clientY 以浏览器左上顶角为原点,定位y轴坐标 // offsetX 以当前事件的目标对象左上角为原点,定位x轴坐标 // offsetY 以当前事件的目标对象左上角为原点,定位y轴坐标 // pageX 以Document 对象(即文本窗口)左上角为原点,定位x轴坐标 // pageY 以Document 对象(即文本窗口)左上角为原点,定位y轴坐标 // screenX 计算机屏幕左上角为原点,定位x轴坐标 // screenY 计算机屏幕左上角为原点,定位y轴坐标 // layerX 最近的绝对定位的父元素(如果没有,则为Document对象)左上角为原点,定位x轴坐标 // layerY 最近的绝对定位的父元素(如果没有,则为Document对象)左上角为原点,定位y轴坐标 const draggable = { inserted: function (el) { el.style.position = 'absolute' el.style.cursor = 'move' el.onmousedown = function (e) { let disx = e.pageX - el.offsetLeft let disy = e.pageY - el.offsetTop document.onmousemove = function (e) { let x = e.pageX - disx let y = e.pageY - disy let 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 + 'px' el.style.top = y + 'px' } document.onmouseup = function () { document.onmousemove = document.onmouseup = null } } } } export default draggable
使用方法
<template> <div class="container"> <div class="draggable_box" v-draggable></div> </div> </template> <script> export default { data() { return { } }, methods: {} } </script> <style lang="scss" scoped> .container { height: 100vh; width: 100vw; position: relative; .draggable_box { height: 100px; width: 100px; border-radius: 50%; border: 1px solid black; } } </style>
二、防抖指令
const debounce = { // 防抖指令 inserted: function (el, binding) { let timer el.addEventListener('click', () => { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { binding.value() }, 500) }) } } export default debounce
使用方法
<template> <div class="container"> <div v-debounce="send"></div> </div> </template> <script> export default { data() { return { } }, methods: { send() { console.log('连续点击') } } } </script> <style lang="scss" scoped> </style>