dataTransfer.getData()在dragover,dragenter,dragleave中无法获取数据的问题

在HTML5的拖拽事件中,dataTransfer.getData()在dragover, dragenter, dragleave事件中返回为空,因这些事件中drag data store处于保护模式。为在dragover时访问dragstart中的数据,可以使用全局变量作为临时存储。同时,dragover事件更适合处理数据,而非立即应用视觉效果,因为样式更改通常在drop后才会生效。" 80603194,7760103,解决Python pandas DataFrame与Series计算axis=1时的RuntimeWarning,"['pandas', 'dataframe', 'python', 'error handling']
部署运行你感兴趣的模型镜像

做拖拽相关效果时,想在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中一样获取不到数据。



您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<script setup lang="ts"> import DrnContextmenu from "@/components/DrnEditorCommon/DrnContextmenu/index.vue"; import DrnContextmenuItem from "@/components/DrnEditorCommon/DrnContextmenuItem/index.vue"; import useStore from "@/store"; import { widgetUtil, stringUtil, jsonUtil } from "doran-web-core"; const { parse } = jsonUtil; import { ref } from "vue"; const { useCopyStore: copyStore } = useStore(); const { renderer } = window.drn; const appStore = parent.appStore; const pageStore = parent.pageStore; const widgetStore = parent.widgetStore; const page = ref(); const contextmenuRef = ref(); const selectWidgetParentRef = ref(); const widgetSource = ref(); const PageComponents = ref(); const widgetType = ref(""); const showEventMenu = ref(false); const widgetParentData: any = ref([]); let currentSelectedWidget: any = ref(); const mountStyle = () => { if (parent?.drn.app.styles?.styleGroup) { window.drn.app.styles.styleGroup = parent.drn.app.styles?.styleGroup; window.drn.app.styles.mountAppStyles(document.head); } if (window.drn.page.styles.styleGroup?.length > 0) { window.drn.page.styles.styleGroup = parent.drn.page.styles?.styleGroup; window.drn.page.styles.mountAppStyles(document.head); } }; const updatePage = () => { // 通过为页面添加和移除class来触发页面重绘 page.value = pageStore.openedPage; if (page.value) { page.value.className = page.value?.className ? page.value?.className : []; page.value.className.push(""); page.value.className.pop(); } mountStyle(); }; page.value = pageStore.openedPage; mountStyle(); appStore.$subscribe(() => { updatePage(); }); pageStore.$subscribe(() => { updatePage(); }); widgetStore.$subscribe(() => { updatePage(); }); const insertWidget = (targetData: any, position: string) => { if (widgetSource.value) { pageStore.openedPage?.moveWidget(widgetSource.value, targetData, position); console.log(widgetSource.value, "111"); widgetStore.selectWidget(widgetSource.value); console.log(widgetStore.selectedWidget, "222"); const prevContainer = document.getElementById(widgetSource.value.id); console.log(widgetSource.value, "+1"); console.log(prevContainer, "+2"); if (prevContainer) { setTimeout(() => { addDropAreaEl(prevContainer); }, 500); } } widgetSource.value = null; }; const drop = (ev: any) => { const realTarget = findTarget(ev.target); const targetId = realTarget?.id; const widget = pageStore.openedPage?.getWidget(targetId); const sourceId = ev.dataTransfer.getData("sourceId"); if (sourceId && sourceId.length > 0) { widgetSource.value = pageStore.openedPage?.getWidget(sourceId); } else { const group = ev.dataTransfer.getData("widget-group"); const type = ev.dataTransfer.getData("widget-type"); if (group && group.length > 0 && type && type.length > 0) { widgetSource.value = widgetUtil.cloneWidgetConfig(type); if (widgetSource.value) { widgetSource.value.id = stringUtil.generateId(); } } } widgetParentData.value = pageStore.openedPage.getParentWidgets( pageStore.openedPage, targetId ); selectWidgetParentRef.value?.show(ev, widget); // const realTarget = findTarget(ev.target); // const targetId = realTarget?.id; // const sourceId = ev.dataTransfer.getData("sourceId"); // let source: any = null; // if (sourceId && sourceId.length > 0) { // source = pageStore.openedPage?.getWidget(sourceId); // } else { // const group = ev.dataTransfer.getData("widget-group"); // const type = ev.dataTransfer.getData("widget-type"); // if (group && group.length > 0 && type && type.length > 0) { // source = widgetUtil.cloneWidgetConfig(type); // if (source) { // source.id = stringUtil.generateId(); // } // } // } // if (source) { // pageStore.openedPage?.moveWidget( // source, // pageStore.openedPage?.getWidget(targetId) // ); // } // ev.target.classList.remove("drn-widget-dragover"); // widgetStore.selectWidget(source); ev.stopPropagation(); }; const dragover = (ev: any) => { ev.preventDefault(); }; const dragstart = (ev: any) => { ev.dataTransfer.setData("sourceId", ev.target.id); ev.dataTransfer.setDragImage(document.createElement("span"), 10, 10); ev.stopPropagation(); }; const dragend = (ev: any) => { const targetId = ev.target.id; const source = pageStore.openedPage?.getWidget(targetId); widgetStore.selectWidget(source); ev.target.classList.remove("drn-widget-dragover"); }; const dragenter = (ev: any) => { ev.target.classList.add("drn-widget-dragover"); }; const dragleave = (ev: any) => { ev.target.classList.remove("drn-widget-dragover"); }; const widgetclick = (ev: any) => { selectedWidget(ev); ev.stopPropagation(); }; // 移除拖拽区域 const removeDropAreaEl = (target: any) => { const dropArea = target.querySelector(".drn-widget-drop-box"); if (dropArea) { target.removeChild(dropArea); } target.classList.remove("selected"); }; // 创建拖拽区域 const addDropAreaEl = (target: any) => { console.log("我走到了+3"); const existingDropArea = target.querySelector(".drn-widget-drop-box"); if (existingDropArea) { console.log("我走到了+4"); return; } console.log("我走到了+5"); const drnDropAreaEl = document.createElement("div"); drnDropAreaEl.className = "drn-widget-drop-box"; drnDropAreaEl.id = "drnDropBox"; const dropImg = new URL("@/assets/img/drop.png", import.meta.url).href; const dropEl = document.createElement("img"); dropEl.id = "drn-widget-dragging_image"; dropEl.className = `drn-widget-drop-img-box`; dropEl.src = dropImg; drnDropAreaEl.appendChild(dropEl); console.log("我走到了+6"); target.appendChild(drnDropAreaEl); console.log("我走到了+7"); console.log(target); }; //处理放置条件,已经添加则返回,没有则添加, const addDropArea = (ev: any) => { console.log("我走到了+1"); const targetWidget = ev.currentTarget; if (currentSelectedWidget.value) { removeDropAreaEl(currentSelectedWidget.value); } console.log("我走到了+2"); currentSelectedWidget.value = targetWidget; addDropAreaEl(targetWidget); console.log("我走到了+n"); }; const widgetmouseove = (ev: any) => { ev.target.classList.add("drn-widget-item-hover"); ev.stopPropagation(); }; const widgetmouseout = (ev: any) => { ev.stopPropagation(); ev.target.classList.remove("drn-widget-item-hover"); }; const selectedWidget = (ev: any) => { const widget = pageStore.openedPage?.getWidget(ev.target.id); if (widget) { widgetStore.selectWidget(widget); } }; const contextmenu = (ev: any) => { ev.stopPropagation(); ev.preventDefault(); selectedWidget(ev); const widget = pageStore.openedPage?.getWidget(ev.target.id); widgetParentData.value = pageStore.openedPage.getParentWidgets( pageStore.openedPage, ev.target.id ); if (widget) { widgetType.value = widget?.type; showEventMenu.value = widget.events?.length > 0 ? true : false; if (widget) { contextmenuRef.value?.show(ev, widget); } } }; const structureBaseProps = (el: any) => { const clazzes = ["drn-widget-item"]; if (el._needMask) { clazzes.push("drn-widget-mask"); } if (el._needWrapper) { clazzes.push("drn-widget-warpper"); } if (widgetStore.selectedWidget && widgetStore.selectedWidget.id === el.id) { clazzes.push("drn-widget-item-selected"); const prevContainer = document.getElementById( widgetStore.selectedWidget.id ); console.log(widgetStore.selectedWidget, "+1"); console.log(prevContainer, "+2"); if (prevContainer) { const mockEvent = { currentTarget: prevContainer, stopPropagation: () => {}, preventDefault: () => {}, }; console.log("我走到了"); // addDropArea(mockEvent); } } if (!widgetStore.selectedWidget) { document .querySelectorAll(".drn-widget-drop-box") .forEach((el) => el.remove()); } return { draggable: true, ondragstart: dragstart, ondragend: dragend, ondragenter: dragenter, ondragleave: dragleave, ondrop: drop, ondragover: dragover, oncontextmenu: contextmenu, onclick: widgetclick, onmouseover: widgetmouseove, onmouseout: widgetmouseout, class: clazzes.join(" "), title: `${el.name} [${el.id}]`, }; }; const findTarget = (el: any) => { let currentEl: any = el; while (currentEl && currentEl.classList) { if ( currentEl.classList.contains("drn-widget-item") || currentEl.classList.contains("drn-page-editor") ) { return currentEl; } currentEl = currentEl.parentNode; } }; const getDragImage = () => { let image: any = document.querySelector("#dragging_image"); const draggingImg = new URL("@/assets/img/dragging.png", import.meta.url) .href; if (!image) { image = document.createElement("img"); image.id = "dragging_image"; image.src = draggingImg; image.style = "position:abslute;right:0;bottom:0;z-index:-1;width:0px;"; document.body.append(image); } return image; }; getDragImage(); PageComponents.value = (props: any) => { const { data } = props; return renderer.render(data, structureBaseProps); }; const copyWidget = (widget: any) => { if (widget) { copyStore.copyWidget(widget); } }; const shearWidget = (widget: any) => { if (widget) { pageStore.openedPage.removeWidget(widget.id); copyStore.shearWidget(widget); } }; const pasteWidget = (widget: any) => { if (copyStore.copiedWidgets) { const newWidget = parse(copyStore.copiedWidgets); if (newWidget) { pageStore.openedPage?.moveWidget( newWidget, pageStore.openedPage?.getWidget(widget.id) ); } widgetStore.selectWidget(newWidget); copyStore.pasteWidget(newWidget); } }; const deleteWidget = (widget: any) => { if (widget) { pageStore.openedPage.removeWidget(widget.id); widgetStore.deselectWidget(); } }; const copyWidgetStyles = (widget: any) => { copyStore.copyWidgetStyles(widget); }; const pasteWidgetStyles = (widget: any) => { if (copyStore.copiedWidgetStyle) { pageStore.openedPage?.modifyWidgetStyle( copyStore.copiedWidgetStyle, pageStore.openedPage?.getWidget(widget.id) ); } }; const copyWidgetEvents = (widget: any) => { copyStore.copyWidgetEvents(widget); }; const pasteWidgetEvent = (widget: any) => { if (copyStore.copiedWidgetEvent) { pageStore.openedPage?.modifyWidgetEvent( copyStore.copiedWidgetEvent, pageStore.openedPage?.getWidget(widget.id) ); } }; const selectWidgetEvent = (item: any) => { widgetStore.selectWidget(item); }; const widgetMouseoveEvent = (item: any) => { const prevContainer = document.getElementById(item.id); if (prevContainer) prevContainer.classList.add("drn-widget-item-hover"); }; const widgetMouseoutEvent = (item: any) => { const prevContainer = document.getElementById(item.id); if (prevContainer) prevContainer.classList.remove("drn-widget-item-hover"); }; document.onkeydown = (ev: KeyboardEvent) => { parent.keyBoardEventHandler(ev, 1); }; </script> <template> <PageComponents :data="page" style="padding: 2px"></PageComponents> <drn-contextmenu ref="contextmenuRef"> <template #default="{ data }"> <div class="drn-contextmenu-item-title"> {{ widgetType !== "DrnPage" ? "组件名称:" : "页面名称:" }}{{ data?.name }} </div> <drn-contextmenu-item separator></drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="copyWidget(data)" > <template #icon> <drn-icon icon="copy"></drn-icon> </template> 复制 (Ctrl + C) </drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="shearWidget(data)" > <template #icon> <drn-icon icon="shear"></drn-icon> </template> 剪切 (Ctrl + X) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgets ? true : false" @click="pasteWidget(data)" > <template #icon> <drn-icon icon="paste"></drn-icon> </template> 粘贴 (Ctrl + V) </drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="deleteWidget(data)" > <template #icon> <drn-icon icon="trashCan"></drn-icon> </template> 删除 (Ctrl + D) </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> <drn-contextmenu-item @click="copyWidgetStyles(data)"> <template #icon> <drn-icon icon="copyStyle"></drn-icon> </template> 复制样式 (Ctrl + Shift + C) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgetStyle ? true : false" @click="pasteWidgetStyles(data)" > <template #icon> <drn-icon icon="pasteStyle"></drn-icon> </template> 粘贴样式 (Ctrl + Shift + V) </drn-contextmenu-item> <drn-contextmenu-item v-if="showEventMenu" separator ></drn-contextmenu-item> <drn-contextmenu-item v-if="showEventMenu" @click="copyWidgetEvents(data)" > <template #icon> <drn-icon icon="copyEvent"></drn-icon> </template> 复制事件 (Ctrl + Alt + C) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgetEvent ? true : false" v-if="showEventMenu" @click="pasteWidgetEvent(data)" > <template #icon> <drn-icon icon="pasteEvent"></drn-icon> </template> 粘贴事件 (Ctrl + Alt + V) </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> <div class="drn-contextmenu-item-title">父级组件</div> <drn-contextmenu-item separator></drn-contextmenu-item> <div v-if="widgetParentData?.length > 0"> <drn-contextmenu-item v-for="item in widgetParentData" @click="selectWidgetEvent(item)" @mouseove="widgetMouseoveEvent(item)" @mouseout="widgetMouseoutEvent(item)" > {{ item.name }} <span v-if="item.props.general?.proConfig?.uniqueName?.value" >[{{ item.props.general?.proConfig?.uniqueName?.value }}]</span > </drn-contextmenu-item> </div> <div v-else class="drn-widget-empty-box">暂无父级</div> </template> </drn-contextmenu> <drn-contextmenu ref="selectWidgetParentRef"> <template #default="{ data }"> <div class="drn-contextmenu-item-title"> {{ widgetType !== "DrnPage" ? "组件名称:" : "页面名称:" }}{{ data?.name }} </div> <drn-contextmenu-item separator></drn-contextmenu-item> <div class="drn-contextmenu-item-title">父级组件</div> <drn-contextmenu-item separator></drn-contextmenu-item> <div v-if="widgetParentData?.length > 0"> <div v-for="item in widgetParentData"> <drn-contextmenu-item title="中间" @click="insertWidget(item, 'center')" @mouseove="widgetMouseoveEvent(item)" @mouseout="widgetMouseoutEvent(item)" > <div class="drn-parent-item-widget-box"> <div> {{ item.name }} <span v-if="item.props.general?.proConfig?.uniqueName?.value" >[{{ item.props.general?.proConfig?.uniqueName?.value }}]</span > </div> <div class="drn-widget-drop-area-box" v-if="item.type != 'DrnPage'" > <div class="drn-widget-drop-area"> <drn-icon icon="top" title="顶部" class="drn-icon" @click.stop="insertWidget(item, 'top')" /> </div> <div class="drn-widget-drop-area"> <drn-icon icon="bottom" title="底部" class="drn-icon" @click.stop="insertWidget(item, 'bottom')" /> </div> </div> </div> </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> </div> </div> <div v-else class="drn-widget-empty-box">暂无父级</div> </template> </drn-contextmenu> </template> <style scoped></style> 上述方法中insertWidget点击完成后创建拖拽小图标,为啥打印出来已经创建上了,但是在页面上没有渲染,上述insertWidget拖拽已有的组件后出现的放置位置的方法,帮我分析原因并给出解决方法
最新发布
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值