vue自定义指令
1、拖拽(包括指定拖拽位置)
import Vue from 'vue'
Vue.directive('drag', {
//这里的el就是获取的元素
bind (el) {
let odiv = el; //获取当前元素
// 判断是否依据父级节点来定位
const dragLimitClass = el.getAttribute('dragLimitClass')
const handleDragClass = el.getAttribute('handleDragClass')
el.onmousedown = (e) => {
const elWidth = el.offsetWidth + 1 // 解决边距被遮挡不显示的问题
const elHeight = el.offsetHeight
if(e.target.className !== handleDragClass) return
// 让页面元素不会被选中
document.onselectstart = () => {
return false;
};
//算出鼠标相对元素的位置
let disX = e.clientX - odiv.offsetLeft;
let disY = e.clientY - odiv.offsetTop;
let left = 0;
let top = 0;
document.onmousemove = (e) => {
const parentDom = document.querySelector(`.${dragLimitClass}`)
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
left = e.clientX - disX;
top = e.clientY - disY;
var docWidth = dragLimitClass ? parentDom?.clientWidth : document.body.clientWidth//网页可见宽
var docHeight = dragLimitClass ? parentDom?.clientHeight : document.body.clientHeight//网页可见高
if (docHeight && top > docHeight - elHeight) {//超下边界
top = docHeight - elHeight
}
if (top < 0) {//超上边界
top = 0
}
if (docWidth && left > docWidth - elWidth) {//超右边界
left = docWidth - elWidth
}
if (left < 0) {//超左边界
left = 0
}
//绑定元素位置到positionX和positionY上面
//移动当前元素
odiv.style.left = left + 'px';
odiv.style.top = top + 'px';
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
document.onselectstart = () => {
return true;
};
};
}
}
})
页面使用:
<div
v-drag
class="attributePop"
handleDragClass="attribute-top"
:dragLimitClass="dragLimitClass"
>
</div>
2、拉伸改变元素大小
import Vue from 'vue'
Vue.directive('resizeable', {
bind(el, binding) {
let startX, startY, startWidth, startHeight;
const handle = document.createElement("div");
handle.style.width = "1rem";
handle.style.height = "1rem";
handle.style.position = "absolute";
handle.style.right = "0";
handle.style.bottom = "0";
handle.style.background = "transparent";
handle.style.cursor = "se-resize";
el.appendChild(handle);
handle.addEventListener("mousedown", (e) => {
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(
document.defaultView.getComputedStyle(el).width,
10
);
startHeight = parseInt(
document.defaultView.getComputedStyle(el).height,
10
);
document.addEventListener("mousemove", resize);
document.addEventListener("mouseup", stopResize);
// 让页面元素不会被选中
document.onselectstart = () => {
return false;
};
});
const limitClass = el.getAttribute('resizeLimitClass')
const isRem = el.getAttribute('isRem')
function resize(e) {
const newWidth = startWidth + e.clientX - startX;
const newHeight = startHeight + e.clientY - startY;
const fontSize = isRem ? document.documentElement.style.fontSize.replace('px','') : 1
if (limitClass) {
const limitEl = el.closest(`.${limitClass}`);
if (limitEl) {
const limitWidth = limitEl.getBoundingClientRect().width;
const limitHeight = limitEl.getBoundingClientRect().height;
if (newHeight + el.offsetTop > limitHeight) {
el.style.height = (limitHeight - el.offsetTop) / fontSize + (isRem ? 'rem' : 'px')
return
}
if (newWidth + el.offsetLeft > limitWidth) {
el.style.width = (limitWidth - el.offsetLeft) / fontSize + (isRem ? 'rem' : 'px')
return
}
}
}
el.style.width = newWidth / fontSize + (isRem ? 'rem' : 'px')
el.style.height = newHeight / fontSize + (isRem ? 'rem' : 'px')
}
function stopResize() {
document.removeEventListener("mousemove", resize);
document.removeEventListener("mouseup", stopResize);
document.onselectstart = () => {
return true;
};
}
},
})
页面使用
<div
v-resizeable
:isRem="true"
class="attributePop"
:resizeLimitClass="resizeLimitClass"
>
</div>
ps:v-drag与v-resizeable可同时使用
3、监听元素大小变化
import Vue from 'vue'
Vue.directive('resize', {
bind(el, binding) {
// el为绑定的元素,binding为绑定给指令的对象
let width = '',
height = ''
function isReize() {
const style = document.defaultView.getComputedStyle(el)
if (width !== style.width || height !== style.height) {
binding.value({ width: style.width, height: style.height }) // 关键(这传入的是函数,所以执行此函数)
}
width = style.width
height = style.height
}
el.__vueSetInterval__ = setInterval(isReize, 300)
},
unbind(el) {
clearInterval(el.__vueSetInterval__)
}
}),
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果