面試的時(shí)候碰到過這樣一個(gè)問題

目錄結(jié)構(gòu)用以下的html文件
<ul id="content">
<li class="list-item">1</li>
<li id="add-li">+</li>
</ul>
首先是右鍵的自定義點(diǎn)擊事件,事件名為contextmenu,綁定到所需要?jiǎng)h除的元素塊里,取消默認(rèn)事件。
dom.oncontextmenu=function (e) {
//e.button判斷鼠標(biāo)的按鍵
if (e.button == 2){
e.preventDefault();
//這里是需要執(zhí)行的語句
}
}
然后模擬快捷菜單,思路就是在指針位置彈出一個(gè)列表,將對話框設(shè)為position:absolute,每次點(diǎn)擊的改變其定位,獲取指針的地方為(e.clientX,e.clientY)
添加元素和刪除元素調(diào)用removeChild()和insertBefore(),需注意的是新添加的元素也得綁定所有的事件。
另外一個(gè)難點(diǎn)就是拖拽事件的,鼠標(biāo)點(diǎn)擊事件有三個(gè)階段mousedown,mousemove,mouseup。mousedown的時(shí)候,獲取當(dāng)前位置,這里使用offsetLeft和offsetTop表示,然后在mousemove的時(shí)候監(jiān)聽鼠標(biāo)位置,然后設(shè)定top和left的值,這樣每個(gè)元素都要設(shè)置為絕對定位,所以初始化的時(shí)候要通過js來設(shè)定列表的位置。
function init() {
var lis = content.getElementsByTagName('li')
for (let i = 0;i<lis.length;i++){
lis[i].style.left = i%4*120+'px';
lis[i].style.top = Math.floor(i/4)*120+'px';
}
}
當(dāng)然,鼠標(biāo)點(diǎn)擊的時(shí)候也需要判斷,不然會(huì)和之前綁定的contextmenu沖突,(左鍵的e.button=0),在mouseup的時(shí)候還要注意取消之前mousemove的事件,不然就會(huì)鼠標(biāo)松開后還一直移動(dòng)。
這里有個(gè)簡單的拖拽demo(這里沒有判斷e.button的值)
var startX, startY, moveX, moveY, x, y;
box.onmousedown = function (e) {
startX = e.clientX;
startY = e.clientY;
x = box.offsetLeft;
y = box.offsetTop;
//為了避免拖動(dòng)出box,事件綁定在document上
document.onmousemove = function (e) {
moveX = e.clientX - startX
moveY = e.clientY - startY
box.style.left = x + moveX + 'px';
box.style.top = y + moveY + 'px';
}
document.onmouseup = function () {
//移除后移除拖動(dòng)事件
document.onmousemove = function () {
return false
}
}
}
最后就是拖拽的交換判斷,這里我做的處理是被拖拽的元素的左上角拖拽到某元素的右下角時(shí),如果滿足,就交換元素里面的內(nèi)容,然后被拖動(dòng)的元素恢復(fù)到原始位置。
function getSwap() {
areaArr=[];
for (var i = 0;i<listArr.length;i++){
var left = listArr[i].offsetLeft;
var top = listArr[i].offsetTop;
areaArr.push({index:i,leftmin:left+50,topmin:top+50,leftmax:left+100,topmax:top+100})
}
}
function swapNum(dom) {
// 獲取元素節(jié)點(diǎn)的交換區(qū)域
for(var i=0;i<areaArr.length;i++){
if (domleft>=areaArr[i].leftmin&&domleft<=areaArr[i].leftmax&&domtop>=areaArr[i].topmin&&domtop<=areaArr[i].topmax) {
console.log(areaArr[i].index)
var target= listArr[i].innerText
listArr[i].innerText = dom.innerText
dom.innerText = target
}
}
}
傳入dom進(jìn)行判斷,然后
完整demo放在了下面的頁面:https://github.com/SNJiang1992/somedemo/blob/master/dragswap.html
待優(yōu)化的部分:
1.綁定事件可以做一個(gè)封裝,后段創(chuàng)建了一個(gè)新的元素后,綁定事件又重復(fù)了一遍。
2.刪除元素時(shí)會(huì)有報(bào)錯(cuò)提示,但是具體原因不是很清楚。