Javascript 如何公开公开 angular 2 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35276291/
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
How to expose angular 2 methods publicly?
提问by Jacques ジャック
I am currently working on porting a Backbone project to an Angular 2 project (obviously with a lot of changes), and one of the project requirements requires certain methods to be accessible publicly.
我目前正在将 Backbone 项目移植到 Angular 2 项目(显然有很多变化),项目要求之一要求某些方法可以公开访问。
A quick example:
一个简单的例子:
Component
成分
@component({...})
class MyTest {
private text:string = '';
public setText(text:string) {
this.text = text;
}
}
Obviously, I could have <button (click)="setText('hello world')>Click me!</button>
, and I would want to do that as well. However, I'd like to be able to access it publicly.
显然,我可以有<button (click)="setText('hello world')>Click me!</button>
,我也想这样做。但是,我希望能够公开访问它。
Like this
像这样
<button onclick="angular.MyTest.setText('Hello from outside angular!')"></click>
Or this
或这个
// in the js console
angular.MyTest.setText('Hello from outside angular!');
Either way, I would like the method to be publicly exposed so it can be called from outside the angular 2 app.
无论哪种方式,我都希望公开该方法,以便可以从 angular 2 应用程序外部调用它。
This is something we've done in backbone, but I guess my Google foo isn't strong enough to find a good solution for this using angular.
这是我们在主干中所做的事情,但我想我的 Google foo 不够强大,无法使用 angular 找到一个好的解决方案。
We would prefer to only expose some methods and have a list of public apis, so if you have tips for doing that as well, it'd be an added bonus. (I have ideas, but others are welcomed.)
我们更愿意只公开一些方法并有一个公共 api 列表,所以如果你也有这样做的技巧,那将是一个额外的好处。(我有想法,但欢迎其他人。)
回答by Günter Z?chbauer
Just make the component register itself in a global map and you can access it from there.
只需让组件在全局映射中注册自己,您就可以从那里访问它。
Use either the constructor or ngOnInit()
or any of the other lifecycle hooksto register the component and ngOnDestroy()
to unregister it.
使用构造函数或ngOnInit()
任何其他生命周期钩子来注册和ngOnDestroy()
取消注册组件。
When you call Angular methods from outside Angular, Angular doesn't recognize model change. This is what Angulars NgZone
is for.
To get a reference to Angular zone just inject it to the constructor
当您从 Angular 外部调用 Angular 方法时,Angular 无法识别模型更改。这就是 AngularsNgZone
的用途。要获得对 Angular zone 的引用,只需将其注入构造函数
constructor(zone:NgZone) {
}
You can either make zone
itself available in a global object as well or just execute the code inside the component within the zone.
您也可以使其zone
自身在全局对象中可用,也可以仅在区域内的组件内执行代码。
For example
例如
calledFromOutside(newValue:String) {
this.zone.run(() => {
this.value = newValue;
});
}
or use the global zone reference like
或使用全局区域参考,如
zone.run(() => { component.calledFromOutside(newValue); });
https://plnkr.co/edit/6gv2MbT4yzUhVUfv5u1b?p=preview
https://plnkr.co/edit/6gv2MbT4yzUhVUfv5u1b?p=preview
In the browser console you have to switch from <topframe>
to plunkerPreviewTarget....
because Plunker executes the code in an iFrame
. Then run
在浏览器控制台中,您必须从 切换到<topframe>
,plunkerPreviewTarget....
因为 Plunker 在iFrame
. 然后运行
window.angularComponentRef.zone.run(() => {window.angularComponentRef.component.callFromOutside('1');})
or
或者
window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');})
回答by Sithija Piyuman Thewa Hettige
This is how i did it. My component is given below. Don't forget to import NgZone. It is the most important part here. It's NgZone that lets angular understand outside external context. Running functions via zone allows you to reenter Angular zone from a task that was executed outside of the Angular zone. We need it here since we are dealing with an outside call that's not in angular zone.
我就是这样做的。我的组件如下。不要忘记导入 NgZone。这是这里最重要的部分。NgZone 让 angular 理解外部环境。通过 zone 运行函数允许您从在 Angular zone 之外执行的任务重新进入 Angular zone。我们在这里需要它,因为我们正在处理不在角度区域内的外部呼叫。
import { Component, Input , NgZone } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'example',
templateUrl: './example.html',
})
export class ExampleComponent {
public constructor(private zone: NgZone, private router: Router) {
//exposing component to the outside here
//componentFn called from outside and it in return calls callExampleFunction()
window['angularComponentReference'] = {
zone: this.zone,
componentFn: (value) => this.callExampleFunction(value),
component: this,
};
}
public callExampleFunction(value: any): any {
console.log('this works perfect');
}
}
now lets call this from outside.in my case i wanted to reach here through the script tags of my index.html.my index.html is given below.
现在让我们从外部调用它。在我的情况下,我想通过我的 index.html.my index.html 的脚本标签到达这里,如下所示。
<script>
//my listener to outside clicks
ipc.on('send-click-to-AT', (evt, entitlement) =>
electronClick(entitlement));;
//function invoked upon the outside click event
function electronClick(entitlement){
//this is the important part.call the exposed function inside angular
//component
window.angularComponentReference.zone.run(() =
{window.angularComponentReference.componentFn(entitlement);});
}
</script>
if you just type the below in developer console and hit enter it will invoke the exposed method and 'this works perfect ' will be printed on console.
如果您只是在开发人员控制台中输入以下内容并按回车键,它将调用公开的方法,并且“这很完美”将打印在控制台上。
window.angularComponentReference.zone.run(() =>
{window.angularComponentReference.componentFn(1);});
entitlement is just some value that is passed here as a parameter.
权利只是在此处作为参数传递的一些值。
回答by Václav ?vára
I was checking the code, and I have faced that the Zone is not probably necessary. It works well without the NgZone.
我正在检查代码,我遇到了可能不需要该区域的情况。它在没有 NgZone 的情况下运行良好。
In component constructor do this:
在组件构造函数中这样做:
constructor(....) {
window['fncIdentifierCompRef'] = {
component = this
};
}
And in the root script try this:
在根脚本中试试这个:
<script>
function theGlobalJavascriptFnc(value) {
try {
if (!window.fncIdentifierCompRef) {
alert('No window.fncIdentifierCompRef);
return;
}
if (!window.fncIdentifierCompRef.component) {
alert('No window.fncIdentifierCompRef.component');
return;
}
window.fncIdentifierCompRef.component.PublicCmpFunc(value);
} catch(ex) {alert('Error on Cmp.PublicCmpFunc Method Call')}
}
</script>
This works to me.
这对我有用。
回答by MatthewScarpino
The problem is that Angular's components are transpiled into modules that aren't as easy to access as regular JavaScript code. The process of accessing a module's features depends on the module's format.
问题是 Angular 的组件被转换成模块,这些模块不像常规 JavaScript 代码那样容易访问。访问模块功能的过程取决于模块的格式。
An Angular2 class can contain static members that can be defined without instantiating a new object. You might want to change your code to something like:
Angular2 类可以包含无需实例化新对象即可定义的静态成员。您可能希望将代码更改为以下内容:
@component({...})
class MyTest {
private static text: string = '';
public static setText(text:string) {
this.text = text;
}
}
回答by zardilior
Super simple solution!! save component or function with an alias outside
超级简单的解决方案!!使用外部别名保存组件或函数
declare var exposedFunction;
@Component({
templateUrl: 'app.html'
})
export class MyApp {
constructor(public service:MyService){
exposedFunction = service.myFunction;
}
at index.html add in head
在 index.html 中添加头部
<script>
var exposedFunction;
</script>
Inside exposed function do not use this. parameters if you need them you will have to use closures to get it to work
内部暴露的函数不要使用这个。参数,如果你需要它们,你将不得不使用闭包来让它工作
This is particularly useful in ionic to test device notifications on web instead of device
这在 ionic 中特别有用,可以在网络而不是设备上测试设备通知