原生js的拖拽排序,如何保存拖拽后的位置?
<ul id="main" class="main" (dragover)="allowDrop($event)">
<li draggable="true" (dragstart)="dragStart($event)" (dragend)="dragEnd($event)" class="card" *ngFor="let item of list">
{{item.name}}
</li>
</ul>
ngAfterViewInit() {
}
// 拖拽开始
dragStart(event) {
this.draging = event.target
event.dataTransfer.getData(this.draging)
}
// 拖拽中
allowDrop(event) {
// 默认无法将数据/元素放置到其他元素中。如果需要设置允许放置,必须阻止对元素的默认处理方式
event.preventDefault();
var target = event.target;
if (target.nodeName === "LI" && target !== this.draging) {
var targetRect = target.getBoundingClientRect();
var dragingRect = this.draging.getBoundingClientRect();
if (target) {
// 判断是否动画元素
if (target.animated) {
return;
}
}
if (this.index(this.draging) < this.index(target)) {
// 目标比元素大,插到其后面
// nextSibling下一个兄弟元素
target.parentNode.insertBefore(this.draging, target.nextSibling)
} else {
// 目标比元素小,插到其前面
target.parentNode.insertBefore(this.draging, target)
}
this.animate(dragingRect, this.draging)
this.animate(targetRect, target)
}
}
// 拖拽完成
dragEnd(event) {
// var target = event.target;
// var draging =this.draging;
// // var tt = JSON.parse(localStorage.getItem('targetRect'));
// localStorage.setItem('targetRect', JSON.stringify(targetRect));
// localStorage.setItem('dragingRect', JSON.stringify(dragingRect));
}
// 获取元素在父元素中的index
index(el) {
var index = 0
if (!el || !el.parentNode) {
return -1
}
// previousElementSibling:上一个兄弟元素
while (el && (el = el.previousElementSibling)) {
index++
}
return index
}
// 触发动画
animate(prevRect, target) {
var ms = 300
if (ms) {
var currentRect = target.getBoundingClientRect()
if (prevRect.nodeType === 1) {
prevRect = prevRect.getBoundingClientRect()
}
this.css(target, 'transition', 'none')
this.css(target, 'transform', 'translate3d(' +
(prevRect.left - currentRect.left) + 'px,' +
(prevRect.top - currentRect.top) + 'px,0)'
);
target.offsetWidth; // 触发重绘
this.css(target, 'transition', 'all ' + ms + 'ms');
this.css(target, 'transform', 'translate3d(0,0,0)');
// 事件到了之后把transition和transform清空
clearTimeout(target.animated);
target.animated = setTimeout(function () {
// this.css(target, 'transition', '');
// this.css(target, 'transform', '');
target.animated = false;
}, ms);
}
}
// 给元素添加style
css(el, prop, val) {
var style = el && el.style
if (style) {
if (!(prop in style)) {
prop = prop;
}
style[prop] = val + (typeof val === 'string' ? '' : 'px')
}
}
在完成拖拽后能保存完成后的位置,下次加载直接加载这个位置。应该如何保存?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用数据驱动的框架、按照数据驱动的原则写应用,当顺序变化的时候就不应该通过
insertBefore
这种方案来修改显示顺序,应该拿到被拖动的 DOM 节点对应数据中list
的哪一项,然后修改这一项在list
中的顺序:这样的话,排序完成的同时就已经知晓
list
的变化了,所以顺便把这个list
转为字符串保存到localStorage
,下次加载的时候从localStorage
里取出来恢复,这样就等于是保存了用户拖拽的结果了。如果仍采用
insertBefore
的方案,那么你需要将item
的原始数据与渲染的DOM
绑定,当用户重新排序后,从所有的li.card
列表中反序列化出排序后的列表,同样采用localStorage
的方案来本地化:还有一种更绝的方案:
后台返回的数据的话,应该由后台存储位置信息,如果前端改变了位置,应该发送请求去改变位置信息。