拖拽时需用event.target.closest('[data-project-id]')获取ID,dragover和drop中必须无条件preventDefault(),绑定后须存localStorage并页面加载时恢复。

拖拽时 dragstart 事件拿不到目标元素的项目 ID?
常见现象是:拖动一个便签(<div class="note">)到项目区域,但 event.target 指向的是子元素(比如标题或图标),导致 dataset.projectId 取不到。
根本原因是拖拽触发点不一定是便签根节点——用户可能点在了 <span> 或 <button> 上。必须主动向上找最近的带 data-project-id 的祖先。
- 在
dragstart回调里用event.target.closest('[data-project-id]')替代直接读event.target.dataset.projectId - 确保每个便签容器(不是内部文字)有
draggable="true",否则dragstart根本不会触发 - 别依赖
event.dataTransfer.setData('text/plain', ...)存 ID——字符串序列化后类型丢失,后续解析易错;改用setData('application/json', JSON.stringify({id: 123}))
drop 事件里阻止默认行为失败,拖拽直接跳转页面?
这是最常被忽略的兼容性坑:Chrome/Firefox 要求 dragover 和 drop 都必须调用 event.preventDefault(),否则浏览器按默认逻辑处理(比如把文本拖进地址栏会发起搜索)。
关键不是“写了没”,而是“什么时候写”——dragover 必须在拖拽进入目标区域前就响应,且不能被条件语句包裹(比如 if (isProjectDropZone) preventDefault() 不行,因为浏览器在判断是否允许 drop 前就检查了)。
立即学习“前端免费学习笔记(深入)”;
-
dragover回调里无条件写event.preventDefault(),哪怕只是空函数 -
drop回调里先preventDefault(),再取event.dataTransfer.getData('application/json') - 别给
drop区域加pointer-events: none——这会让拖拽事件完全透传,dragover根本收不到
绑定项目后刷新页面,便签和项目关系就丢了?
HTML 拖拽本身不保存状态,它只是触发一次交互。所谓“关联”,本质是你在 drop 时执行了某段 JS(比如发请求、改本地数据),但没做持久化。
如果期望刷新后仍显示关联关系,必须把绑定结果存在可恢复的地方:localStorage、URL 参数,或者服务端数据库。DOM 属性(如 data-project-id)在重载后就清空了。
- 绑定成功后,立刻更新便签 DOM:
noteEl.dataset.boundProjectId = projectId,同时存入localStorage.setItem('note_project_map', JSON.stringify(map)) - 页面加载时,遍历所有便签,从
localStorage查对应项目 ID,并添加视觉标记(比如加个boundclass) - 避免用
innerHTML重绘整个便签列表——会丢掉已绑定的dataset,改用element.setAttribute()单独更新属性



















