在 Angular 2 中使用 Highlight JS

Using Highlight JS in Angular 2

我正在尝试在我的 Angular 2 应用程序中使用 Highlight JS,当代码块不是静态信息时,我在弄清楚如何使用它时遇到了一些麻烦。我的意思是,代码字符串来自服务器通过 http get 调用。

所以,如果我有这个:

export  class   WorkstationComponent implements OnInit  {

    private submission = new Submission();
    private criteria = new Array<ExerciseCriteria>();
    private codeString:string = `
        /* HelloWorld.java
        */

        public class HelloWorld
        {
            public static void main(String[] args) {
                System.out.println("Hello World!");
            }
        }`;

    constructor(private _router:Router, private submissionService:SubmissionService,
                private activatedRoute:ActivatedRoute){}

    @ViewChild('code') codeElement: ElementRef;

ngOnInit(){
    this.activatedRoute.params
        // (+) converts string 'id' to a number
        .switchMap((params: Params) => this.submissionService.getSubmission(+params['id']))
        .subscribe(data => this.success(data),
                    error => this.fail(error));

}

success(data:any){
    this.submission = data;
    this.criteria = data.criteria;
    hljs.highlightBlock(this.codeElement.nativeElement);
}

没问题...

但是,如果我改为

success(data:any){
    this.submission = data;
    this.criteria = data.criteria;
    this.codeString = data.code;
    hljs.highlightBlock(this.codeElement.nativeElement);
}

我明白了:

我做错了什么? HTML 是一样的

                <pre>
                    <code #code highlight class="java">
                        {{codeString}}
                    </code>
                </pre>

如@PankajParkar 评论中所述,highlightBlockcodeString 绑定得到评估之前就开始火了。

推迟 运行 此功能到下一个报价单(使用 setTimeout)将起作用,因为它将允许 Angular 进行更改检测和 DOM 更新。

另一种解决方案是使用管道。这是我使用 Prism.js 用于代码突出显示的管道。您可以轻松更新它以使用 Highlight.js:

@Pipe({ name: 'prism' })
export class PrismPipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {}
  transform(value, args) {
    if (!isString(value)) {
      throw new InvalidPipeArgumentException(PrismPipe, value);
    }
    let lang = args[0].toString().trim().toLowerCase();

    let grammar = Prism.languages[lang];
    // fallback to clike
    if (!grammar) grammar = Prism.languages.clike;
    return this.sanitizer.bypassSecurityTrustHtml(Prism.highlight(value, grammar));
  }
}

然后我在这样的代码中使用它:

<pre [innerHtml]="codeString.source | prism:codeString.lang"></pre>

这是因为 highlightBlock 函数在内部 code 元素内容不可用之前启动。解决方案之一是 setTimeout 应用 highlightBlock 一个勾后,一旦所有绑定都被应用。但不必要的是,这将使 运行 成为另一个变化检测。

与其等待内部内容以 DOM 为界,不如手动将其应用于 DOM 的 textContent,然后应用 highlightBlock 函数。

代码

success(data:any){
    this.submission = data;
    this.criteria = data.criteria;
    this.codeString = data.code;
    //making sure code is populated by below line
    this.codeElement.nativeElement.textContent = data.code;
    hljs.highlightBlock(this.codeElement.nativeElement);
}

在 Angular4 中,要使用来自组件的 highlight.js:

import {Component, ViewEncapsulation} from '@angular/core';
import * as hljs from 'highlight.js';

@Component({
    selector: 'cus-com',
    template: `
    <pre>
        <code [innerHtml]="html_content"></code>
    </pre>`,
    encapsulation: ViewEncapsulation.None,
    styles: [require('highlight.js/styles/github.css')]
})
export class CustomComponentsComponent {
    languages = ['html', 'typescript'];
    html_content = hljs.highlightAuto('<h1 class="big">Title</h1>', this.languages).value;  
}