拖拽: 做个指令美美哒
0. 缘起
不太开心,以为闲着了又改了,心情不好,不过组长啪啪就把这个写好了,我可以抄一抄。虽然遇到了蜜汁的问题!
1. 指令
这里写了个指令,指令的官网文档说道
除了核心功能默认内置的指令 (
v-model
和v-show
),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
指令钩子函数会被传入以下参数:
-
el
:指令所绑定的元素,可以用来直接操作 DOM。 -
binding
:一个对象,包含以下 property:
name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
2. 拖拽的指令版实现
2.1 A split B样式
注意A与split必须绝对定位,B的左边距即为A宽度
A{
position: absolute;
height: calc(100vh - 230px);
padding: 10px;
overflow-y: auto;
box-sizing: border-box;
}
split{
position: absolute;
left: 307px;
height: calc(100vh - 220px);
background-color: #87c1db;
width: 2px;
cursor: move;
}
B{
width: calc(100% - 300px);
box-sizing: border-box;
height: 100% !important;
flex: 1;
padding: 30px;
font-size: 12px;
margin-left: 300px;
}
2.2 局部指令v-move
directives: {
move: {
// 指令的定义
inserted: function (el) {},
bind: function (el) {
el.onmousedown = (event) => {
event.stopPropagation();
event.preventDefault();
const left = document.getElementsByClassName("A")[0];
const right = document.getElementsByClassName("B")[0];
// 记录下初始位置的值
let disX = event.clientX;
el.left = el.offsetLeft;
document.onmousemove = function (e) {
let moveX = e.clientX - disX; // 鼠标拖动的偏移距离
let iT = el.left + moveX ; // 分隔条相对父级定位的 left 值
el.style.left = `${iT}px`;
left.style.width = `${iT - 2}px`;
right.style.width = `calc(100% - ${iT}px)`;
right.style.marginLeft = `${iT}px`;
return false;
};
// 鼠标放开的时候取消操作
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
};
};
},
},
},
2.3 挂载在split上
<div class="spilt" v-move></div>
3. 原版的mousedown\mousemove\mouseup
Js利用拖拽实现的改变大小 - 简书 (jianshu.com)
首先鼠标按下(
onmousedown
)
- 记录目标元素当前的
left
和top
值鼠标移动(
onmousemove
)
- 计算每次移动的横向距离 (
disX
) 和纵向距离 (disY
)- 并改变元素的
left
(left = left + disX
)和top
(top = top + disY
)值鼠标松开(
onmouseup
)
- 完成一次拖拽,做一些收尾工作
作者:Essentric
链接:https://juejin.cn/post/6844903958633267208
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4. HTML5的拖拽事件
HTML5拖放API Drag and Drop - 掘金 (juejin.cn)
详解javascript拖拽(一)基础介绍 - 掘金 (juejin.cn)
preventDefault
拖动文件到浏览器中,浏览器会默认打开该文件,需要手动阻止该默认行为。在
dragover
、drop
中阻止默认行为:preventDefault.
后期修复的一个BUG
有一个更新数据获取的操作,如果拖拽后点更新数据,会有左右两侧重叠的奇怪样子(因为width和margin-left未能随着数据更新改变)
。这个问题我的解决方法是重置初始状态,每次获取新数据就都挪到一开始的位置。原来的想法是记录当前位置,可是自定义指令都是只读值,没法出来,而且computed的也没法实时记录宽度。
let left = document.getElementsByClassName("tree")[0];
let right = document.getElementsByClassName("table-footer")[0];
let splitLine = document.getElementsByClassName("split-div")[0];
left.style.width = "300px";
right.style.marginLeft = "300px";
splitLine.style.left = "327px";