【问题标题】:Angular2 dynamically insert script tagAngular2动态插入脚本标签
【发布时间】:2017-01-21 05:35:58
【问题描述】:

我正在从服务器内容获取到 json 对象字段,它是 html、<style></style><script></script> 标记,我想像这样执行它:

[innerHtml]="content | sanitize",但<script></script> 标签不执行。有没有可能让它发挥作用?

我的消毒管道如下所示:

import {Pipe} from '@angular/core';
import {DomSanitizationService} from '@angular/platform-browser';

@Pipe({
    name: 'sanitize',
    pure: true
})
export class Sanitize {
    constructor(private sanitizer: DomSanitizationService) {

    }

    transform(html: string) {

        return this.sanitizer.bypassSecurityTrustHtml(html);
    }
}

我知道,DomSanitizationService 中有 bypassSecurityTrustScript 功能,但我该如何使用呢?

【问题讨论】:

  • json对象长什么样子?你想转换什么?
  • html 是否添加到 DOM 中?您是否在浏览器控制台中收到错误消息?
  • 内容如下所示:"
    some html
    "
  • 不执行
  • Html 正确添加到 dom

标签: javascript html angular angular2-services


【解决方案1】:

这将解决问题...

import { Pipe } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
  name: 'sanitize',
  pure: true
})
export class Sanitize {

  constructor(private domSanitizer: DomSanitizer) { }


  handleExternalScriptsInHtmlString(string) {
    let that = this;
    var parser = new DOMParser();
    var scripts = parser.parseFromString(string, 'text/html').getElementsByTagName('script');
    var results = [];

    for (var i = 0; i < scripts.length; i++) {
      var src = scripts[i].getAttribute('src');
      if (src.length && results.indexOf(src) === -1) {
        results.push(src);
        that.addScript(src);
      }
    }

    return results;
  }

  addScript(src) {
    var script = document.createElement('script');
    script.setAttribute('src', src);
    document.body.appendChild(script);
  }


  transform(htmlContent: any) {
    let sanitizeHtmlContent = this.domSanitizer.bypassSecurityTrustHtml(htmlContent);

    this.handleExternalScriptsInHtmlString(htmlContent);

    return sanitizeHtmlContent;
  }
}

【讨论】:

    【解决方案2】:

    没有角度的方式......你需要这样做......

    import { Pipe } from '@angular/core';
    import { DomSanitizer } from '@angular/platform-browser';
    
    @Pipe({
      name: 'sanitize',
      pure: true
    })
    export class Sanitize {
    
      constructor(private domSanitizer: DomSanitizer) { }
    
    
      handleExternalScriptsInHtmlString(string) {
        let that = this;
        var parser = new DOMParser();
        var scripts = parser.parseFromString(string, 'text/html').getElementsByTagName('script');
        var results = [];
    
        for (var i = 0; i < scripts.length; i++) {
          var src = scripts[i].getAttribute('src');
          if (src.length && results.indexOf(src) === -1) {
            results.push(src);
            that.addScript(src);
          }
        }
    
        return results;
      }
    
      addScript(src) {
        var script = document.createElement('script');
        script.setAttribute('src', src);
        document.body.appendChild(script);
      }
    
    
      transform(htmlContent: any) {
        let sanitizeHtmlContent = this.domSanitizer.bypassSecurityTrustHtml(htmlContent);
    
        this.handleExternalScriptsInHtmlString(htmlContent);
    
        return sanitizeHtmlContent;
      }
    }
    

    【讨论】:

    • 这也有同样的问题,对吧?因为你仍然只是得到一个你必须使用不执行脚本标签的 innerHtml 显示的变量
    • @SeanKPS 没有这个实际上会执行脚本标签。注意函数 addScript。我们正在手动查找脚本标签并将它们显式添加到 DOM
    • 我认为 Angular 根本不会执行脚本标签——即使它们在 DOM 中。也许这仅在组件模板中,并且在直接附加到正文时不适用。尽管如此,我还是需要将脚本输出准确地放在 DOM 中脚本标记的位置,对于 Github Gists,我最终编写了几个函数来对其进行排序。
    【解决方案3】:

    不是angular 2的问题,通过innerHTML插入的script标签没有被执行。

    如果您的 html 字符串包含 script 标记,请以这种方式插入:

    const fragment = document.createRange().createContextualFragment(yourHtmlString);
    anyElement.appendChild(fragment);
    

    【讨论】:

    • 完美运行
    • 对于其他可能需要在某些时候向正文添加脚本,但故意不希望它在初始页面加载时与应用程序的其余部分一起引导的其他人:document.body.appendChild(fragment) 也可以工作Alex 的代码的第二行,而不是在 Angular 中设置 ViewChild。
    猜你喜欢
    • 2019-02-13
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    相关资源
    最近更新 更多