Angular 6 img元素选择器指令无法作用于StencilJS生成img元素的问题咨询
核心原因
你的推测完全正确,当前实现没有配置错误、也不是逻辑遗漏:
Angular的元素选择器匹配机制有明确的边界——它只会扫描、匹配Angular模板编译流程中生成的DOM节点,完全不会感知外部框架(比如StencilJS)在自身运行时独立创建的DOM元素。StencilJS作为基于Web Component的框架,它生成的img标签要么是自身组件渲染流程中创建的内部DOM、要么属于Shadow DOM范围,完全脱离了Angular的模板解析和DOM扫描范围,自然不会触发你写的img选择器指令的实例化。
可选解决方案
全局DOM监听方案(推荐)
既然需求是覆盖全文档范围内所有img元素,不需要依赖Angular指令的匹配机制,直接用浏览器原生的MutationObserver做全局DOM监听即可:- 把原来写在
ImgElementDirective构造函数里的图片处理逻辑,全部迁移到已有的ImageProcessorService中 - 在应用初始化阶段(比如根组件的
ngOnInit生命周期)启动全局监听,配置MutationObserver监听整个文档的子树节点变化,匹配所有新增的img节点 - 对捕获到的未处理img节点,直接调用
processImage方法完成逻辑
这个方案完全不受Angular的DOM扫描边界限制,不管是Angular模板内的img、Stencil组件生成的img、甚至是任意JS代码动态插入的img都能覆盖,原有的ImgElementDirective可以直接删除,减少冗余代码。
- 把原来写在
手动绑定指令实例方案
如果一定要保留现有指令的封装结构,可以在通过MutationObserver捕获到外部新增的img元素后,通过Angular的ApplicationRef获取全局依赖注入器,手动实例化ImgElementDirective,把外部img的ElementRef传给指令完成绑定。注意这个方案需要自行管理指令实例的销毁逻辑,避免因为img元素被移除导致的内存泄漏。调整组件DOM结构方案
如果使用的Stencil组件是自有团队维护、可修改源码的,可以把需要处理的img标签从组件的Shadow DOM中移到Light DOM插槽范围内。这部分DOM是在Angular的模板上下文中渲染的,可以正常被现有img选择器指令匹配到。但这个方案灵活性差,无法覆盖无源码的第三方Stencil组件,仅作为特殊场景的备选。
内容的提问来源于stack exchange,提问作者thesentiment

