marko 的 dependencychain 仅在编译期静态记录路径顺序,须传入确定路径如 ./header.marko,不可用动态字符串;每个 taglib 需新建实例,循环引用会致编译报错。

Marko 的 DependencyChain 类怎么用才不丢依赖
Marko 的 DependencyChain 不是运行时调度器,它只在编译期静态记录路径顺序。你不能靠它触发组件加载或同步状态,它只服务于构建流程中的文件拓扑排序。
常见错误是把它当 runtime 依赖管理器用:比如在模板里写 await import('./widget.marko') 还指望 DependencyChain 自动 resolve,结果发现构建产物里根本没包含那个文件——因为 Marko 编译器只扫描显式 include 或 import 语句,不解析字符串拼接或动态路径。
-
append()必须传入确定的、可静态分析的路径字符串,例如dependencyChain.append('./header.marko');传`./${name}.marko`会直接被忽略 - 每个
taglib加载点都要新建链,不能复用同一个实例——new DependencyChain([path])是起点,后续所有append都基于该快照 - 调试时看
toString()输出,如果出现[A → B → A]就说明存在循环引用,编译会报错,不是运行时卡住
HTML 模板里声明 data-prereq 后 JS 怎么响应
data-prereq 是纯标记,浏览器不会自动处理它。必须配合集中协调器(如 window.$deps)和事件监听才能生效。
典型陷阱是只写 <my-chart data-prereq="auth-provider,config-loader"></my-chart>,却不注册 component:ready 事件监听器,导致下游组件永远等不到就绪信号。
- 上游组件就绪后必须显式 dispatch
new CustomEvent('component:ready', { detail: { id: 'auth-provider' } }) - 协调器收到事件后,只更新
document.querySelectorAll('[data-prereq~="auth-provider"]'),注意是属性值包含匹配,不是 CSS 选择器语法 - 下游组件在
connectedCallback里检查this.dataset.prereq?.split(',').every(id => window.$deps.has(id)),而不是查 DOM 是否存在
为什么 customElements.define 里不能直接查依赖组件
因为此时自定义元素可能还没注册,DOM 树也未必挂载完成。哪怕目标组件已写在 HTML 里,customElements.get('auth-provider') 在 define 调用时刻仍可能返回 undefined。
错误写法:class MyWidget extends HTMLElement { constructor() { super(); const auth = document.querySelector('auth-provider'); /* 此时 auth 一定是 null */ }}
- 查询必须延后到
connectedCallback,且用requestIdleCallback(() => { /* 查找逻辑 */ }, { timeout: 5000 })避免阻塞渲染 - 查之前先确认是否已定义:
if (!customElements.get('auth-provider')) return,否则querySelector即使找到节点,其内部状态也可能未初始化 - 设
data-waiting-for属性并加 class 如pending,让 CSS 控制 loading 状态,别靠 JS 轮询
WeakMap 缓存代理对象时最容易漏掉什么
WeakMap 本身不会泄漏,但缓存时机和清理时机不对,会导致响应失效或内存滞留。最常漏的是:组件卸载时没删缓存,而新组件又用了相同 key。
例如一个 user-card 组件用 WeakMap 缓存了对 user 数据的 Proxy,页面切换后旧实例被 GC,但若没在 disconnectedCallback 里调 weakMap.delete(this),下次同名组件创建时可能复用旧代理,读到过期数据。
- 代理对象必须在
connectedCallback中创建,在disconnectedCallback中销毁对应缓存 - 不要用组件 DOM 节点本身作 WeakMap 键——它可能被框架复用(如 Vue 的
v-if切换),应改用Symbol()或crypto.randomUUID()生成唯一 ID 存为data-component-id - 数组代理需单独重写原型方法,
push/splice不走set拦截器,漏掉就会丢失响应性
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











