|
|
@@ -15,32 +15,38 @@
|
|
|
*/
|
|
|
import type { Directive } from 'vue'
|
|
|
|
|
|
-const ANCHORS = new WeakMap<Element, Comment>()
|
|
|
+interface Rec { a: Comment; nodes: Node[] }
|
|
|
+const ANCHORS = new WeakMap<Element, Rec>()
|
|
|
|
|
|
function unwrap(el: Element): void {
|
|
|
const parent = el.parentNode
|
|
|
if (!parent) return
|
|
|
- const anchor = document.createComment('v-unwrap')
|
|
|
- ANCHORS.set(el, anchor)
|
|
|
- parent.insertBefore(anchor, el)
|
|
|
- while (el.firstChild) parent.insertBefore(el.firstChild, anchor)
|
|
|
+ const rec: Rec = { a: document.createComment('v-unwrap'), nodes: [] }
|
|
|
+ ANCHORS.set(el, rec)
|
|
|
+ parent.insertBefore(rec.a, el)
|
|
|
+ while (el.firstChild) { const n = el.firstChild; parent.insertBefore(n, rec.a); rec.nodes.push(n) }
|
|
|
parent.removeChild(el)
|
|
|
}
|
|
|
|
|
|
-/** 把宿主当前(Vue 刚写入的)子节点移到锚点之前。 */
|
|
|
+/** 把宿主当前(Vue 刚写入的)子节点移到锚点之前;**先移除上次同步的节点**(否则旧子视图会堆积)。 */
|
|
|
function resync(el: Element): void {
|
|
|
- const anchor = ANCHORS.get(el)
|
|
|
- const parent = anchor && anchor.parentNode
|
|
|
- if (!anchor || !parent) return
|
|
|
- while (el.firstChild) parent.insertBefore(el.firstChild, anchor)
|
|
|
+ const rec = ANCHORS.get(el)
|
|
|
+ const parent = rec && rec.a.parentNode
|
|
|
+ if (!rec || !parent) return
|
|
|
+ for (const n of rec.nodes) if (n.parentNode === parent) parent.removeChild(n)
|
|
|
+ rec.nodes = []
|
|
|
+ while (el.firstChild) { const n = el.firstChild; parent.insertBefore(n, rec.a); rec.nodes.push(n) }
|
|
|
}
|
|
|
|
|
|
export const vUnwrap: Directive<HTMLElement> = {
|
|
|
mounted: (el) => unwrap(el),
|
|
|
updated: (el) => resync(el),
|
|
|
beforeUnmount: (el) => {
|
|
|
- const anchor = ANCHORS.get(el)
|
|
|
- if (anchor && anchor.parentNode) anchor.parentNode.removeChild(anchor)
|
|
|
- ANCHORS.delete(el)
|
|
|
+ const rec = ANCHORS.get(el)
|
|
|
+ if (rec) {
|
|
|
+ const parent = rec.a.parentNode
|
|
|
+ if (parent) { for (const n of rec.nodes) if (n.parentNode === parent) parent.removeChild(n); parent.removeChild(rec.a) }
|
|
|
+ ANCHORS.delete(el)
|
|
|
+ }
|
|
|
},
|
|
|
}
|