如何使带#id 的锚 link 在 Angular 中按预期工作

How to make anchor link with #id work as expected in Angular

我的html内容是由后端的markdown编译器生成的,我想要angular做的是从服务器获取数据,动态渲染内容并显示。

mock markdown内容可能是这样的:

<h1 id="test1">Test 1<a href="#test1" title="Permanent link">&para;</a></h1>
<h1 id="test2">Test 2<a href="#test2" title="Permanent link">&para;</a></h1>

foo.component.html中,我使用innerHTML属性来显示内容,像这样:

<div [innerHTML]="mock_markdown_content"></div>

现在,那些锚标签上的 link 将变成 localhost:4200/#test1 之类的东西,并且无法按预期导航到这些元素的位置。

由于 html 内容是由 markdown 编译器生成的,我不想更改 html 内容本身。

实际上,这个foo.component在浏览器中显示的urllink是类似localhost:4200/post/post-title的东西,所以这些锚点的预期url标签是 localhost:4200/post/post-title#test1.

我发现 Angular 的官方指南可以完全满足我的要求,例如: https://angular.io/guide/router#overview (正确显示 url 并可以导航到元素位置)。他们是如何实施的?

  1. 依赖注入和变量声明
import { Renderer2 } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

constructor(
  private renderer: Renderer2,
  private domSanitizer: DomSanitizer
) {}

content: SafeHtml;
private mockMarkdownContent = '<h1 id="test1">Test 1<a href="#test1" title="Permanent link">&para;</a></h1>';
  1. 将字符串转换为 DOM (reference)
const template = this.renderer.createElement('template');
template.innerHTML = this.mockMarkdownContent.trim();
  1. 修改锚点(
const anchorNodes: NodeList = template.content.querySelectorAll('a');
const anchors: Node[] = Array.from(anchorNodes);
for (const anchor of anchors) {
  const href: string = 
    (anchor as HTMLAnchorElement).getAttribute('href');
  if (href.indexOf('#') === 0) {
    this.renderer.setProperty(
      anchor,
      'href',
      `/prefix/link/here${href}`
     );
  }
}
  1. 阻止 Angular 清理 HTML 字符串 ()
this.content = 
  this.domSanitizer.bypassSecurityTrustHtml(template.innerHTML);
  1. 在HTML模板中绑定处理过的内容
<div [innerHTML]="content"></div>