Javascript 在 Angular 组件模板中添加脚本标签
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38088996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding script tags in Angular component template
提问by Ian Belcher
Angular2 removes <script>
tags automatically from templates to stop people using this functionality as a "poor's man" loader.
Angular2 会<script>
自动从模板中删除标签,以阻止人们将此功能用作“穷人”加载器。
The issue here is that script tags currently have more uses than just loading code or other script files. There is the possibility that further functionality around <script>
tags will be introduced in future as well.
这里的问题是脚本标签目前的用途不仅仅是加载代码或其他脚本文件。<script>
将来也有可能会引入更多围绕标签的功能。
One current use is JSON-LD which takes the format
目前的一种用途是采用以下格式的 JSON-LD
<script type="application/ld+json">
{
"@context":"http://schema.org",
"@type":"HealthClub",
...
}
</script>
A commonly suggested work around is to dynamically add script tagsto the document via the ngAfterViewInit
hook, but this is obviously not proper ng2 practice and will not work server side, which JSON-LD obviously needs to be able to do.
通常建议的解决方法是通过钩子将脚本标签动态添加到文档中ngAfterViewInit
,但这显然不是 ng2 的正确做法,并且不会在服务器端工作,而 JSON-LD 显然需要能够做到这一点。
Are there any other workarounds that we can use to include <script>
tags in angular2 templates (even if the tag is inert within the browser) or is this a case of the framework being too opinionated? What other solutions might exist if this situation can't be solved in angular2?
是否有任何其他解决方法可用于<script>
在 angular2 模板中包含标签(即使标签在浏览器中是惰性的),或者这是框架过于固执的情况吗?如果在 angular2 中无法解决这种情况,还有哪些其他解决方案?
采纳答案by Nicky
Maybe a little late to the party here, but since the above answers do not work well with Angular SSR (e.g. document is not defined
server-side or document.createElement is not a function
), I decided to write a version that works for Angular 4+, in both server and browser context:
也许在这里聚会有点晚了,但是由于上述答案不适用于 Angular SSR(例如document is not defined
服务器端或document.createElement is not a function
),我决定编写一个适用于 Angular 4+ 的版本,在服务器和浏览器上下文中:
Component Implementation
组件实现
import { Renderer2, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
class MyComponent implements OnInit {
constructor(
private _renderer2: Renderer2,
@Inject(DOCUMENT) private _document: Document
) { }
public ngOnInit() {
let script = this._renderer2.createElement('script');
script.type = `application/ld+json`;
script.text = `
{
"@context": "https://schema.org"
/* your schema.org microdata goes here */
}
`;
this._renderer2.appendChild(this._document.body, script);
}
}
Service Implementation
服务实施
NOTE: Services cannot use Renderer2
directly. In fact, rendering an element is supposed to be done by a Component. However, you might find yourself in situation where you want to automate the creation of JSON-LD script
tags on a page. As an example, a situation could be to invoke such function on route navigation change events. Hence I decided to add a version that works in a Service
context.
注意:服务不能Renderer2
直接使用。实际上,渲染元素应该由 Component 完成。但是,您可能会发现自己希望script
在页面上自动创建 JSON-LD标签。例如,一种情况可能是在路线导航更改事件上调用此类函数。因此我决定添加一个在Service
上下文中工作的版本。
import { Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
/**
* Use a Service to automate creation of JSON-LD Microdata.
*/
class MyService {
constructor(
@Inject(DOCUMENT) private _document: Document
) { }
/**
* Set JSON-LD Microdata on the Document Body.
*
* @param renderer2 The Angular Renderer
* @param data The data for the JSON-LD script
* @returns Void
*/
public setJsonLd(renderer2: Renderer2, data: any): void {
let script = renderer2.createElement('script');
script.type = 'application/ld+json';
script.text = `${JSON.stringify(data)}`;
renderer2.appendChild(this._document.body, script);
}
}
回答by Günter Z?chbauer
There is no Angular2 way of adding a script tag to a template.
没有将脚本标记添加到模板的 Angular2 方法。
Using require(...)
to load external scripts from the components class was mentioned as a workaround (haven't tried it myself)
使用require(...)
从组件类加载外部脚本被认为是一种解决方法(我自己没有尝试过)
To dynamically add a script tag use
动态添加脚本标签使用
constructor(private elementRef:ElementRef) {};
ngAfterViewInit() {
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "http://somedomain.com/somescript";
this.elementRef.nativeElement.appendChild(s);
}
See also angular2: including thirdparty js scripts in component
回答by Ketan Yekale
The following works with Angular 5.2.7:
以下适用于 Angular 5.2.7:
The required imports are:
所需的进口是:
import { Inject, AfterViewInit, ElementRef } from '@angular/core';
import { DOCUMENT } from '@angular/common';
Implement AfterViewInit:
实现 AfterViewInit:
export class HeroesComponent implements AfterViewInit {
If your component is implementing more that one interfaces, separate them by comma; for example:
如果您的组件正在实现多个接口,请用逗号分隔它们;例如:
export class HeroesComponent implements OnInit, AfterViewInit {
Pass the below arguments to constructor:
将以下参数传递给构造函数:
constructor(@Inject(DOCUMENT) private document, private elementRef: ElementRef) { }
Add ngAfterViewInit method of view life-cycle:
添加视图生命周期的 ngAfterViewInit 方法:
ngAfterViewInit() {
const s = this.document.createElement('script');
s.type = 'text/javascript';
s.src = '//external.script.com/script.js';
const __this = this; //to store the current instance to call
//afterScriptAdded function on onload event of
//script.
s.onload = function () { __this.afterScriptAdded(); };
this.elementRef.nativeElement.appendChild(s);
}
Add afterScriptAdded member function.
添加 afterScriptAdded 成员函数。
This function will be called after the external script is loaded successfully. So the properties or functions you want to use from external js will be accessed in the body of this function.
该函数会在外部脚本加载成功后调用。因此,您要从外部 js 使用的属性或函数将在此函数的主体中访问。
afterScriptAdded() {
const params= {
width: '350px',
height: '420px',
};
if (typeof (window['functionFromExternalScript']) === 'function') {
window['functionFromExternalScript'](params);
}
}
回答by Mohsen M. Galal
ActuallyThere is no Angular2way of adding a script tagto a template.
but you can do some trickfirst of allyou will import AfterViewInit
and ElementRef
from angular2
like this :
实际上,没有Angular2方法可以将脚本标记添加到模板中。但你可以先做一些技巧,你将像这样从 angular2导入AfterViewInit
和导入ElementRef
:
import {Component,AfterViewInit,ElementRef} from 'Angular2/core';
thenyou will you will implement them in your class like that :
那么你会像这样在你的班级中实现它们:
export class example1 implements AfterViewInit{}
and here is a very simple javascript dom trick you gonna do
这是你要做的一个非常简单的javascript dom技巧
export class example1 implements AfterViewInit{
ngAfterViewInit()
{
var s=document.createElement("script");
s.type="text/javascript";
s.innerHTML="console.log('done');"; //inline script
s.src="path/test.js"; //external script
}
}
回答by Giggs
const head = document.getElementsByTagName('head')[0];
const _js = document.createElement('script');
_js.type = 'text/javascript';
_js.appendChild(document.createTextNode('{your js code here}'));
head.appendChild(_js);
this can be placed anywhere one wishes and it's a good approach
这可以放在任何你想要的地方,这是一个很好的方法