2016-09-08 75 views
0

時防止元素的點擊比方說,我已經通過RxJS用於拖n個墨滴這個簡單的代碼:RxJS:如何使用拖放ñ下降

const { fromEvent } = Rx.Observable; 
const target = document.querySelector('.box'); 

const mouseup = fromEvent(target, 'mouseup'); 
const mousemove = fromEvent(document, 'mousemove'); 
const mousedown = fromEvent(target, 'mousedown'); 

document.getElementById("click") 
.addEventListener("click",() => { 
    alert('clicked'); 
}) 

const mousedrag = mousedown.selectMany((md) => { 
    const startX = md.clientX + window.scrollX, 
     startY = md.clientY + window.scrollY, 
     startLeft = parseInt(md.target.style.left, 10) || 0, 
     startTop = parseInt(md.target.style.top, 10) || 0; 
    md.preventDefault(); 
    return mousemove.map((mm) => { 
    mm.preventDefault(); 
    return { 
     left: startLeft + mm.clientX - startX, 
     top: startTop + mm.clientY - startY 
    }; 
    }).takeUntil(mouseup); 
}); 

const subscription = mousedrag.subscribe((pos) => { 
    target.style.top = pos.top + 'px'; 
    target.style.left = pos.left + 'px'; 
}); 

並帶簡單HTML

<div class="box"> 
    <a id="click">Click test</a> 
</div> 

DEMO

現在,如果您單擊並拖動該框,它就可以拖動。但是,如果你點擊「點擊測試」並拖動它,它就會確定,但是在你停止拖動之後,就會顯示提示。如何避免這種情況?

preventDefault不起作用,因爲我們點擊了孩子。 stopPropagation不會也行,因爲我們將停止傳播,但警告單擊處理程序是在包裝盒上的孩子

回答

1

mousedownclick是兩個不同的事件。 AFAIK你不能阻止另一個。但是你可以在你的rx代碼中設置一個特定的類名,然後在點擊處理程序中對這個類進行測試。在mouseup事件,你可以再次刪除類。由於此事件在click事件處理程序可以發生之前調用,因此我已使用setTimeout將它放回到事件循環中。如果您對如何做到這一點有了更好的瞭解,請告訴我。

請參閱fiddle(用RxJS 5編寫)。

全碼:

const { fromEvent } = Rx.Observable; 
const target = document.querySelector('.box'); 

const mouseup = fromEvent(target, 'mouseup'); 
const mousemove = fromEvent(document, 'mousemove'); 
const mousedown = fromEvent(target, 'mousedown'); 

document.getElementById("click") 
    .addEventListener("click", function(event) { 
    if (!event.target.classList.contains('rx-drag')) { 
     alert('clicked'); 
    } 
    }); 

const mousedrag = mousedown.mergeMap((md) => { 
    const startX = md.clientX + window.scrollX, 
     startY = md.clientY + window.scrollY, 
     startLeft = parseInt(md.target.style.left, 10) || 0, 
     startTop = parseInt(md.target.style.top, 10) || 0; 

    md.target.classList.add('rx-drag'); 
    md.preventDefault(); 
    return mousemove.map((mm) => { 
    mm.preventDefault(); 
    return { 
     left: startLeft + mm.clientX - startX, 
     top: startTop + mm.clientY - startY 
    }; 
    }).takeUntil(mouseup.do(() => { 
    setTimeout(() => { 
     md.target.classList.remove('rx-drag'); 
    }); 
    })); 
}); 

const subscription = mousedrag.subscribe((pos) => { 
    target.style.top = pos.top + 'px'; 
    target.style.left = pos.left + 'px'; 
}); 
+0

作品,但基本上它是一個黑客攻擊(如果我有4-5標籤這是在不同的組件):/我的想法是增加一個鉤子來記錄點擊事件與useCapture,然後使用preventDefault()和stopPropogation(如果出現鼠標移動事件),或者取消它。但我沒有設法使它工作。 – gerasalus