專案綜述
- 在頁面中模擬某作業系統的操作介面,提供應用視窗的最大化、最小化、還原等功能
需求
- 對一個應用視窗標題欄雙擊使其鋪滿整個視口,再次雙擊還原到原來大小,和位置
- 部分程式碼片段如下:
win.addEventListener('dblclick', (event) => {
if (cache && cache.status === 'normal') {
Win.maximize(id);
} else if (cache && cache.status === 'maximize') {
Win.restore(id);
}
});
- 在Win.restore()和Win.maximize()方法中通過id讀取該應用的快取資訊
{
top: app.cache.pos.top,
left: app.cache.pos.left,
width: app.size.width,
height: app.size.height,
}
問題
-
Chrome瀏覽器(87)
- 使用電腦自帶觸控板進行雙擊測試,正常
- 使用滑鼠進行雙擊測試,雙擊事件觸發後cache.pos內的內容丟失,top和left屬性不存在,cache中其餘屬性正常
-
Edge瀏覽器(87)
- 表現與Chrome瀏覽器一致
-
Firefox瀏覽器(84)
- 在使用電腦自帶觸控板和滑鼠測試時,雙擊事件觸發後均出現cache.pos內的內容丟失的情況,其餘屬性正常
猜想
- 物件巢狀深度問題???畢竟巢狀最深的丟了,其他的都沒事
// 將left和top直接定義在cache,表現與之前測試結果一致,修改無效
{
top: app.cache.top,
left: app.cache.left,
width: app.size.width,
height: app.size.height,
}
- 命名衝突問題???
// 將屬性名加上字首,表現與之前測試結果一致,修改無效
{
top: app.cache.winTop,
left: app.cache.winLeft,
width: app.size.width,
height: app.size.height,
}
-
事件衝突問題,該元素同時定義了單擊事件,但註釋掉單擊事件後問題依舊存在
-
雙擊事件的BUG????????
// 使用單擊事件模擬雙擊事件,在谷歌和Edge中使用觸控板最大化和還原也會造成資料丟失了
function doubleclick(elem, onsingle, ondouble) {
if (dblFlag) {
dblFlag = true;
setTimeout(function () {
if (dblFlag) {
onsingle(elem);
}
dblFlag = false;
}, 300);
} else {
dblFlag = false;
ondouble(elem);
}
}
解決
-
就在我已經快要放棄這個功能的時候,發現這個元素還繫結了另外一個事件
-
為了讓視窗可以在頁面中自由拖動,加入了mousedown,mousemove,mouseup事件模擬拖拽事件,提前宣告變數currentLeft和currentTop,在mousemove時修改兩個屬性的值,在mouseup時儲存當前位置,如下程式碼:
window.onmouseup = function () {
window.onmousemove = null;
app.cache.pos.left = currentLeft;
app.cache.pos.top = currentTop;
return false;
}
- 在雙擊事件中連續觸發了mouseup和mousedown,所以給top和left寫入了新值
但是,雙擊事件並沒有觸發到mousemove事件,導致currentLeft和currentTop沒有值寫入,還是初始的未賦值狀態,並將undefined寫入了快取,也就是cache.pos內屬性丟失的問題
- 知道了問題就好解決了,加一個判空就行了
window.onmouseup = function () {
window.onmousemove = null;
app.cache.pos.left = currentLeft || app.cache.pos.left;
app.cache.pos.top = currentTop || app.cache.pos.top;
return false;
}
- 至於使用觸控板和使用滑鼠導致差異,大概是用滑鼠手比較穩,雙擊不會出現位置移動,而觸控板兩次點選很難都點中同一位置,或多或少有差異,觸發mousemove寫入了新值
- 不同瀏覽器的不同表現,大概是對雙擊事件中兩次點選的誤差範圍規定不同,改用了單擊事件模擬雙擊事件後,瀏覽器的表現就一致了
反思
- 能給初始值就給初始值,不能給初始值在使用的時候一定要給預設值!
- 別瞎想,看看自己的猜想,連邊都沒有摸到,在用單擊事件模擬雙擊時就應該聯想到其餘的事件,然後檢查是否相互影響
- 就自己目前的水平,所有的問題都一定是自己的問題!
- 自己坑起自己來果然是不遺餘力啊!