dataTransfer.getData()在dragover,dragenter,dragleave中無法獲取數據的問題

做拖拽相關效果時,想在ondragover時給被拖拽元素添加一些樣式,於是在dragover事件的函數中通過dataTransfer.getData()獲取在dragstart中設置的數據,然而發現dataTransfer.getData()所返回的數據爲空。

查詢資料發現dataTransfer.setData()中所設置的數據是存儲在drag data store中,而根據W3C標準,drag data store有三種模式,Read/write mode, Read-only mode跟Protected mode。


W3C Working Draft中5.7.2.關於三種drag data store mode的定義


A drag data store mode, which is one of the following:

Read/write mode
For the dragstart event. New data can be added to the drag data store.

Read-only mode
For the drop event. The list of items representing dragged data can be read, including the data. No new data can be added.

Protected mode
For all other events. The formats and kinds in the drag data store list of items representing dragged data can be enumerated, but the data itself is unavailable and no new data can be added.



Read/write mode
讀/寫模式,在dragstart事件中使用,可以添加新數據到drag data store中。

Read-only mode
只讀模式,在drop事件中使用,可以讀取被拖拽數據,不可添加新數據。

Protected mode
保護模式,在所有其他的事件中使用,數據的列表可以被枚舉,但是數據本身不可用且不能添加新數據。



這樣就可以解釋爲什麼dragover中dataTransfer.getData()返回的數據爲空,以及在dragover時dataTransfer中的types不爲0了,因爲在除了dragstart,drop以外的事件,包括dragover,dragenter,dragleave中,drag data store出於安全原因處於保護模式,因此不可訪問。

如果要實現dragover中訪問dragstart中設置的數據,可以採用定義一個全局變量的方法,在dragstart中賦值,之後在dragend中清空。


另外,我在ondragover時,嘗試給被拖拽元素添加class以改變其樣式發現,雖然拖拽時class已經改變,但在拖拽過程中樣式並沒有改變,而是等到拖拽動作完成後,也就是drop之後樣式才被應用上去,所以在dragover,dragenter,dragleave中做得更多的應該是對數據的處理,而不是應用效果。




另一個問題


我的項目在Chrome中所使用的情況完全符合上述描述,但是在運行如下代碼時dragover,dragenter,dragleave中均可獲取到dataTransfer中的數據。

<!doctype html>
<html>
<head>

</head>
<body>
<li id="oSource" data-name="source element" draggable="true" 

style="display:block;cursor:pointer;width:80px;height:50px;">測試錨</li>
<div id="oTarget"><span>將測試錨拖曳到這裏</span></div>
</body>
<script>
function $(dom) {
	return document.querySelectorAll(dom);
}

$("#oSource")[0].ondragstart = function(event)
{
	event.dataTransfer.setData("text", event.target.getAttribute("data-name"));
}

$("#oTarget")[0].ondragover = function(event)
{
	event.preventDefault();
	var sAnchor = event.dataTransfer.getData("text");
	console.log(sAnchor + " being dragged");
}

$("#oTarget")[0].ondrop = function(event)
{
	event.preventDefault();
	var sAnchor = event.dataTransfer.getData("text");
	console.log(sAnchor + " dropped");
	$("#oTarget")[0].innerText = sAnchor;
}
</script>
</html>


待解釋。

————————————————————————

update 2016/5/15 18:42
關於上述問題

上面那個示例可以在dragover中通過dataTransfer.getData()獲取數據的原因是我直接打開文檔運行了,如果放到wamp中一樣獲取不到數據。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章