|
@@ -5,18 +5,42 @@
|
|
|
* 而旧页是把同一段 HTML **直接注入**页签容器(无宿主)⇒ 结构/样式计数不一致。
|
|
* 而旧页是把同一段 HTML **直接注入**页签容器(无宿主)⇒ 结构/样式计数不一致。
|
|
|
* 该指令在挂载后解包,使**运行时 DOM 与 v2.9.2 完全一致**。
|
|
* 该指令在挂载后解包,使**运行时 DOM 与 v2.9.2 完全一致**。
|
|
|
*
|
|
*
|
|
|
|
|
+ * ★P64 修(实逮):原先只在 `mounted` 解包一次 ⇒ 宿主被移出文档后,Vue 后续 `v-html` 的更新
|
|
|
|
|
+ * 全部写进**已脱离文档的宿主** ⇒ 表现为"点子选项卡页面不变"(振动融合分析的 5 个子视图)。
|
|
|
|
|
+ * 现在挂载时先插入**注释锚点**(子节点移到锚点前、宿主移出文档),并在 `updated` 时把宿主
|
|
|
|
|
+ * 新写入的子节点再同步到锚点之前 ⇒ 既保持"无宿主"的 DOM 口径,又能随数据/子视图变化更新。
|
|
|
|
|
+ *
|
|
|
* 注:SSR 不执行指令,故结构对拍工具(`tools/struct_diff*.mjs`)对带 `unwrap-host` 类的
|
|
* 注:SSR 不执行指令,故结构对拍工具(`tools/struct_diff*.mjs`)对带 `unwrap-host` 类的
|
|
|
* 元素做等价**解包**后再比 —— 判据与运行时口径一致。
|
|
* 元素做等价**解包**后再比 —— 判据与运行时口径一致。
|
|
|
*/
|
|
*/
|
|
|
import type { Directive } from 'vue'
|
|
import type { Directive } from 'vue'
|
|
|
|
|
|
|
|
|
|
+const ANCHORS = new WeakMap<Element, Comment>()
|
|
|
|
|
+
|
|
|
function unwrap(el: Element): void {
|
|
function unwrap(el: Element): void {
|
|
|
const parent = el.parentNode
|
|
const parent = el.parentNode
|
|
|
if (!parent) return
|
|
if (!parent) return
|
|
|
- while (el.firstChild) parent.insertBefore(el.firstChild, el)
|
|
|
|
|
|
|
+ const anchor = document.createComment('v-unwrap')
|
|
|
|
|
+ ANCHORS.set(el, anchor)
|
|
|
|
|
+ parent.insertBefore(anchor, el)
|
|
|
|
|
+ while (el.firstChild) parent.insertBefore(el.firstChild, anchor)
|
|
|
parent.removeChild(el)
|
|
parent.removeChild(el)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 把宿主当前(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)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
export const vUnwrap: Directive<HTMLElement> = {
|
|
export const vUnwrap: Directive<HTMLElement> = {
|
|
|
mounted: (el) => unwrap(el),
|
|
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)
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|