最近研究拖拽生成頁面,遇到一個跨iframe拖拽的功能的問題。在此記錄下心得。git
頁面裏面的 iframe 在沒有跨域的狀況下,SortableJS 是支持跨iframe拖拽的,官方倉庫給了例子。若是跨域了,咱們拿不到 iframe 的 contentDocument,沒法監聽事件,因此 Sortable 默認狀況下是不能工做的。github
理論上 Sortable 是經過監聽事件來完成拖拽的功能,咱們手動構造 drag 事件,通知 Sortable,也是能夠完成任務的。跨域
拖拽須要處理三個事件節點dom
Sortable 一開始不會在 dom 節點加上 draggable 屬性,必須點擊了纔會,因此模擬時,須要先觸發一個 pointdown 事件,而後觸發 dargstrat 事件post
var downEvent = new PointerEvent("pointerdown", { // pointerId: 1, bubbles: true, cancelable: true, // pointerType: "touch", width: 100, height: 100, isPrimary: true, });
var startE = new DragEvent("dragstart", { bubbles: true });
父頁面的 dragover 事件不會傳遞到 iframe 內(廢話),因此咱們只能在 iframe 內監聽 mousemove 事件, 而後構造一個 dragover 事件,傳遞給dom,告訴 Sortable 咱們拖動了Sortable元素到該dom上面,看看是否是須要改變位置。spa
document.addEventListener("mousemove", (e) => { console.log(e.type); if (e.target.classList.contains("list-group-item")) { e.target.dispatchEvent( new DragEvent("dragover", { clientY: e.clientY, bubbles: true }) ); // 用mousemove代替 } })
觸發被拖拽 dom 的 dragend 事件便可code
dragEl.dispatchEvent(new DragEvent("dragend"));
在頁面中模擬拖拽成功後,接下來就是分開成兩個頁面,經過 postMessage 通信事件
這裏把隱藏的 Sortable 實例稱做影子節點
, 在父頁面開始拖拽某個 dom 時,iframe 內部須要同時觸發一個 pull mode 的拖拽開始事件,而且將父頁面拖拽的 dom 的 innerHTML 寫入到影子節點get