一、組件介紹
Vue是一個優秀的前端框架,能夠幫助開發者快速構建優秀的Web應用程序。其中,拖拽排序組件是一種非常實用的UI組件,能夠幫助用戶進行元素的拖拽、移動等操作,提高用戶的使用效率。
本文介紹的這個組件使用Vue框架實現,使用簡單,且支持多種常見的拖拽排序功能,包括拖拽移動、交換位置、拖拽排序、拖拽刪除等,非常適用於需要拖拽排序的場合,包括網頁排版、圖片庫管理等領域。
二、組件應用
下面是一個使用Vue實現的可拖拽排序組件的例子,供讀者參考使用:
<template>
<ul class="drag-list">
<li
v-for="(item, index) in list"
:key="index"
:class="{ active: activeIndex === index }"
@mousedown="handleMousedown(index, $event)"
@mousemove="handleMousemove(index, $event)"
@mouseup="handleMouseup(index)"
:style="getStyle(index)"
>
{{ item }}
<i class="delete" @click="handleDelete(index)"></i>
</li>
</ul>
</template>
<script>
export default {
data() {
return {
list: ["元素1", "元素2", "元素3", "元素4", "元素5", "元素6", "元素7"],
activeIndex: -1,
dragStartPos: { x: 0, y: 0 },
draggingPos: { x: 0, y: 0 },
distanceX: 0,
distanceY: 0,
dragging: false
};
},
methods: {
handleMousedown(index, e) {
this.activeIndex = index;
this.dragging = true;
this.dragStartPos.x = e.pageX;
this.dragStartPos.y = e.pageY;
this.draggingPos.x = e.pageX;
this.draggingPos.y = e.pageY;
},
handleMousemove(index, e) {
if (this.dragging) {
this.distanceX = e.pageX - this.draggingPos.x;
this.distanceY = e.pageY - this.draggingPos.y;
this.draggingPos.x = e.pageX;
this.draggingPos.y = e.pageY;
const targetIndex = this.getTargetIndex(index, e);
if (targetIndex !== index) {
this.list.splice(targetIndex, 0, this.list.splice(index, 1)[0]);
this.activeIndex = targetIndex;
}
// 限制拖動範圍
const limitList = document.querySelector(".drag-list");
const limitTop = limitList.offsetTop;
const limitBottom = limitList.offsetHeight + limitTop;
if (e.pageY limitBottom) {
window.scrollTo(0, window.pageYOffset + 10);
}
}
},
handleMouseup(index) {
if (this.dragging) {
this.dragging = false;
if (this.distanceX !== 0 || this.distanceY !== 0) {
this.list.splice(this.activeIndex, 1);
this.list.splice(index, 0, this.list[this.activeIndex]);
}
this.activeIndex = -1;
this.distanceX = 0;
this.distanceY = 0;
}
},
handleDelete(index) {
this.list.splice(index, 1);
},
getStyle(index) {
if (this.dragging && this.activeIndex === index) {
return {
transform: `translate(${this.distanceX}px, ${this.distanceY}px)`,
zIndex: 99
};
}
},
getTargetIndex(index, e) {
const targetEle = document.elementFromPoint(
e.clientX - this.distanceX,
e.clientY - this.distanceY
);
if (targetEle.classList.contains("delete")) {
return index;
} else {
const targetList = targetEle.parentNode;
const targetIndex = Array.prototype.indexOf.call(
targetList.children,
targetEle
);
return targetIndex;
}
}
}
};
</script>
<style>
.drag-list {
list-style-type: none;
padding: 0;
margin: 0;
border: 1px solid #ccc;
}
.drag-list li {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
border-top: 1px solid #eee;
}
.drag-list li:hover {
background-color: #f0f0f0;
}
.drag-list .active {
background-color: #aad8d3;
color: #fff;
}
.drag-list i {
color: red;
cursor: pointer;
}
</style>
這是一個簡單而功能強大的可拖拽排序組件,解釋代碼如下:
- 在data中定義list,用來存儲排序列表數據
- 該組件提供四個事件回調函數:handleMousedown、handleMousemove、handleMouseup、handleDelete。handleMousedown事件綁定到列表元素上,當用戶鼠標按下時會觸發該事件;handleMousemove事件綁定到列表元素上,當用戶拖動元素時會多次觸發該事件;handleMouseup事件綁定到列表元素上,當用戶鬆開鼠標時會觸發該事件;handleDelete事件綁定到每個元素的刪除按鈕。組件內部通過判斷拖拽距離是否為0,來判斷是否需要進行元素的排序。
- getStyle函數用來設置被拖拽元素的樣式
- getTargetIndex函數用來獲取列表位置
三、組件優化方案
雖然上面的組件已經實現拖拽排序的功能,但是在特定情況下,該組件還有較大的優化空間,可以提高程序的性能和用戶體驗。以下是優化方案:
1、使用window.requestAnimationFrame()
使用requestAnimationFrame()方法代替mousemove()事件,可以在不阻塞瀏覽器的情況下,讓組件流暢地運行。
handleMousemove(index, e) {
if (this.dragging) {
window.requestAnimationFrame(() => {
// 處理拖拽元素的位置變化等邏輯
})
}
}
2、使用位運算優化性能
在複雜的拖拽操作中,位運算可以幫助提升一些性能,比如位移運算、按位與運算等。
handleMousemove(index, e) {
if (this.dragging) {
window.requestAnimationFrame(() => {
const deltaX = e.pageX - this.draggingPos.x;
const deltaY = e.pageY - this.draggingPos.y;
const targetIndex =
(Math.round(e.pageY / this.$refs.itemHeight) - 1) * this.cols +
Math.round(e.pageX / this.$refs.itemWidth) -
1;
// 處理拖拽元素的位置變化等邏輯
})
}
}
3、使用CSS3動畫和transition
在標準的頁面布局中,大量使用JS來實現可視化效果,這種實現方式會造成過多的DOM操作和樣式請求,導致頁面重新渲染。如果我們使用CSS3動畫和transition,我們就可以在不佔用js的情況下,通過GPU加速來快速渲染頁面。
.drag-list li {
transition: transform .2s ease-out;
}
4、使用虛擬列表
在長列表中,可能存在大量的DOM節點渲染,這一過程可能比較耗時,影響用戶體驗。使用虛擬列表方案,可以只渲染列表中可視化的部分,避免過多的DOM操作。
<template>
<div class="drag-list">
<div :style="{ height: itemHeight * rowCount + 'px' }"></div>
<div
ref="listWrapper"
:style="{ height: wrapperHeight }"
@scroll="onScroll"
>
<ul :style="{ transform: 'translateY(' + scrollTop + 'px)' }">
<li
v-for="(item, index) in visibleList"
:key="item.id"
:style="{ top: (index % cols) * itemHeight + 'px', left: Math.floor(index / cols) * itemWidth + 'px' }"
@mousedown="handleMousedown(index, $event)"
@mouseup="handleMouseup(index)"
>
{{ item.value }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
computed: {
visibleList() {
const start = Math.floor(this.scrollTop / this.itemHeight) * this.cols;
const end = start + (this.rowCount + 1) * this.cols;
return this.dataList.slice(start, end);
}
},
methods: {
onScroll() {
this.scrollTop = this.$refs.listWrapper.scrollTop;
}
}
};
</script>
<style>
.drag-list {
position: relative;
}
.drag-list ul {
position: absolute;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
}
.drag-list li {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
border: 1px solid #ddd;
box-sizing: border-box;
}
.drag-list li:hover {
background: #f8f8f8;
}
</style>
四、總結
本文介紹了使用Vue框架實現的可拖拽排序組件,並提供了一些常見的優化方案,可以幫助開發者提高程序的性能和用戶體驗。在實際應用中,我們還可以根據具體情況進行進一步的優化,讓程序更加符合用戶需求。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/311406.html
微信掃一掃
支付寶掃一掃