我已按HTML
方法加载http.get()
页面,并将此页面的内容添加到div标记。
getRequestToAssignPage (param: string) : any {
return this.$http.get(param)
.map((res: Response) => {
this.status = res;
return res.text();
})
.toPromise()
.then(response => {
let restr: string = response;
restr = restr.replace(/(<head[^>]*)(?:[^])*?\/head>/ig, '')
.replace(/(<(\/?)body([^>]*?)>)/g, '')
.replace(/(<style[^>]*)(?:[^])*?\/style>/g, '')
.replace(/(<(\/?)html([^>]*?)>)/g, '')
.replace(/(<app-root[^>]*)(?:[^])*?\/app-root>/ig, '')
.replace(/(<\?[\s\S]*?\?>)|(<!DOCTYPE\s+\w+\s+\[[\s\S]*?\]>)|(<!\w[\s\S]*?>)/g, '')
.replace(/(href\s*=\s*(?:"))/ig, 'href="/#')
.replace(/(href\s*=\s*(?:'))/ig, "href='/#");
this.response = restr;
})
.catch(error => this.status = error );
}
您如何看待此方法,将响应放在变量中,并通过正则表达式解析字符串 好的,然后我将它添加到div,就像这个
<div [innerHTML]="response | safe"></div>
好,我的页面显示。但是,脚本不起作用。它们存在于div标签中,但不会执行。
我曾尝试用eval()
做到这一点,但结果很差
let scripts: string[] = restr.match(/\<scr[\s\S]*?ipt>/g);
this.srcfield.nativeElement.innerHTML = '';
scripts.forEach((value, index) => {
eval.call(null, (this.srcfield.nativeElement.innerHTML = value));
});
SyntaxError:意外的标记&lt;
为什么innerHTML
没有执行加载的脚本代码?我怎么能解决这个问题?
答案 0 :(得分:7)
基于Adam的解决方案,您可以实现自定义指令以及管道并将脚本重新插入DOM。这将解决这两种情况:内联脚本和&#34; src&#34;脚本。请记住,允许这样的脚本非常危险。
管:
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({ name: 'safeHtml' })
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(html) {
return this.sanitizer.bypassSecurityTrustHtml(html);
}
}
指令:
import { Directive, ElementRef, OnInit } from '@angular/core';
@Directive({ selector: '[runScripts]' })
export class RunScriptsDirective implements OnInit {
constructor(private elementRef: ElementRef) { }
ngOnInit(): void {
setTimeout(() => { // wait for DOM rendering
this.reinsertScripts();
});
}
reinsertScripts(): void {
const scripts = <HTMLScriptElement[]>this.elementRef.nativeElement.getElementsByTagName('script');
const scriptsInitialLength = scripts.length;
for (let i = 0; i < scriptsInitialLength; i++) {
const script = scripts[i];
const scriptCopy = <HTMLScriptElement>document.createElement('script');
scriptCopy.type = script.type ? script.type : 'text/javascript';
if (script.innerHTML) {
scriptCopy.innerHTML = script.innerHTML;
} else if (script.src) {
scriptCopy.src = script.src;
}
scriptCopy.async = false;
script.parentNode.replaceChild(scriptCopy, script);
}
}
}
用法:
<div [innerHTML]="myDynamicMarkup | safeHtml" runScripts></div>
答案 1 :(得分:5)
在模板中,您可以设置如下内容:
<div #htmlContainer [innerHTML]="trustedHTML"></div>
在相应的组件中,您可以将HTML加载到模板中,构建一个脚本标记数组,每个标记标记eval
:
@ViewChild('htmlContainer') container;
ngOnInit() {
this.http.get('html-file.html').subscribe((res: Response) => {
this.trustedHTML = this.sanitizer.bypassSecurityTrustHtml(res.text());
setTimeout(() => { //wait for DOM rendering
let scripts = this.container.nativeElement.getElementsByTagName('script');
for (let script of scripts){
eval(script.text)
}
})
});
我讨厌我不得不使用setTimeout
和eval
来寻找看似简单的东西,但它确实有效。
...但不适用于<script src="...
。我最终导入jQuery并使用$(parent).load(url);
。如果有人有纯粹的Angular解决方案,请发布。