我的最终目标是让用户创建HTML(来自数据库),能够在Angular SPA中导航。从后端显示HTML的简单方法是使用DomSanitizer然后绑定到某个元素的innerHTML
。当用户创建的内容中的锚标记<a href="/path/to/diffrent/page/in/app">
重新启动应用程序时,会出现问题。我想到了3个解决方案,他们都有问题。
注意:我想充分利用AOT和构建优化器。
(使用JIT编译器的动态组件)
用户创建的内容将具有类似<a [routerLink]="/path/to/diffrent/page/in/app">
的角度语法。然后使用加载运行时编译器JitCompilerFactory
和自定义装饰器的示例here将组件和模块元数据保存到JIT编译组件,并将用户创建的内容作为模板。但是对于构建优化器,这需要restoring the ctorParameters。有了这个,你就无法获得AOT的所有大小优势,因为你仍然需要加载JIT编译器并按照here - “
由于编译器受内部变化的影响,因此它似乎存在风险。它适用于@ angular / compiler @ 4.4.5,但可能不适用于其他版本。“
(DOM操作)
在用户创建的内容<a href="/path/to/diffrent/page/in/app">
中保留适当的HTML。然后在绑定到innerHTML
后获取ElementRef,然后找到每个锚标记并覆盖click事件。这种DOM操作在角度上似乎非常气馁。
(自定义窗口事件)
用户创建的内容将类似于<a onclick="window.someGlobalFunc("/path/to/diffrent/page/in/app")">
。然后以某种方式听一个角度的窗口事件。我更喜欢这个想法,因为它完全超出角度。
编辑添加:
实现此功能的正确方法是什么?
编辑更新:
我接受了一个答案作为“最佳”选项,但如果有人发现或他们发布了“Angular”方式,请添加答案。
答案 0 :(得分:1)
我遇到了同样的问题并通过创建自定义指令向动态内容的容器添加click
- 侦听器来解决它,如果目标是锚元素,则检查每次单击。如果它是一个锚元素阻止默认行为并采用href
- 属性,请将其用作router.navigateByUrl
的网址。
private onClick(e: any) {
let link = this.checkForParentLink(e.target as HTMLElement);
if(link && link.getAttribute('href')) {
let href = link.getAttribute('href');
let isMailOrPhone = href.startsWith('mailto:') || href.startsWith('tel:');
if(isMailOrPhone) return;
e.preventDefault();
if(link.getAttribute('target') === '_blank') {
let win = window.open(href, '_blank');
win && win.focus();
} else {
this.router.navigateByUrl(href);
}
}
}
private checkForParentLink(element: HTMLElement): HTMLLinkElement {
if(!element) return;
if(element.tagName === 'A') {
return element as HTMLLinkElement;
// this.element.nativeElement is in this case the container element
}
if(element.parentNode === this.element.nativeElement) {
return null;
}
return this.checkForParentLink(element.parentNode as HTMLElement);
}