如何公开公开 angular 2 方法?

IT技术 javascript angular
2021-03-09 16:22:59

我目前正在将 Backbone 项目移植到 Angular 2 项目(显然有很多变化),项目要求之一要求某些方法可以公开访问。

一个简单的例子:

零件

@component({...})
class MyTest {
    private text:string = '';
    public setText(text:string) {
        this.text = text;
    }
}

显然,我可以有<button (click)="setText('hello world')>Click me!</button>,我也想这样做。但是,我希望能够公开访问它。

像这样

<button onclick="angular.MyTest.setText('Hello from outside angular!')"></click>

或这个

// in the js console
angular.MyTest.setText('Hello from outside angular!');

无论哪种方式,我都希望公开该方法,以便可以从 angular 2 应用程序外部调用它。

这是我们在主干中所做的事情,但我想我的 Google foo 不够强大,无法使用 angular 找到一个好的解决方案。

我们更愿意只公开一些方法并有一个公共 api 列表,所以如果你也有这样做的技巧,那将是一个额外的好处。(我有想法,但欢迎其他人。)

5个回答

只需让组件在全局映射中注册自己,您就可以从那里访问它。

使用构造函数或ngOnInit()任何其他生命周期钩子来注册和ngOnDestroy()取消注册组件

当您从 Angular 外部调用 Angular 方法时,Angular 无法识别模型更改。这就是 AngularsNgZone的用途。要获得对 Angular zone 的引用,只需将其注入构造函数

constructor(zone:NgZone) {
}

您也可以使其zone自身在全局对象中可用,也可以仅在区域内的组件内执行代码。

例如

calledFromOutside(newValue:String) {
  this.zone.run(() => {
    this.value = newValue;
  });
}

或使用全局区域参考,如

zone.run(() => { component.calledFromOutside(newValue); });

https://plnkr.co/edit/6gv2MbT4yzUhVUfv5u1b?p=preview

在浏览器控制台中,您必须从 切换到<topframe>plunkerPreviewTarget....因为 Plunker 在iFrame. 然后运行

window.angularComponentRef.zone.run(() => {window.angularComponentRef.component.callFromOutside('1');})

或者

window.angularComponentRef.zone.run(() => {window.angularComponentRef.componentFn('2');})
好的,所以我需要为我所有的公共方法制作辅助方法。非常感谢您的帮助,顺便说一句。
2021-05-05 16:22:59
因此,在创建注册任务的服务时,我遇到了与开始使用之前相同的问题zone.run(()=>{})The method is registered,我可以毫无问题地调用它,但是,似乎没有运行更改检测。 window.widget[name] = () => { window.zone.run(() => { scope[callbackMethod](); }); }; scope上面是组件,我调用的方法是callbackMethod. 有小费吗?
2021-05-08 16:22:59
@k11k2 我不知道什么是剃刀页面,也不知道它们与 ngZone 有何关系
2021-05-12 16:22:59
现在 angular 不包括剃刀页面,所以 ngZone 不适用于这种情况,对吗?否则我的假设是错误的?
2021-05-13 16:22:59
我很欣赏 plunkr,但问题是我有一个外部服务在 window.widget 对象上添加方法。我可以调用这些方法,但不会触发更改检测。看起来您的示例包含我未使用外部服务时使用的内容。(我可能只是报废该外部服务。)感谢您的帮助。
2021-05-16 16:22:59

我就是这样做的。我的组件如下。不要忘记导入 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');
        }
    }

现在让我们从外部调用它。在我的情况下,我想通过我的 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>

如果您只是在开发人员控制台中键入以下内容并按回车键,它将调用公开的方法,并且“这很完美”将打印在控制台上。

 window.angularComponentReference.zone.run(() =>
{window.angularComponentReference.componentFn(1);});

权利只是在此处作为参数传递的一些值。

当心 !!在 angular with 之外公开函数() => {}不适用于 IE它不会被 Angular 转译。你应该使用function() { }
2021-04-16 16:22:59
为什么需要zone,可以直接调用window.angularComponentReference.componentFn(entitlement)。有效?
2021-04-29 16:22:59
我已投赞成票,因为您的答案比公认的答案要清楚得多,恕我直言
2021-05-01 16:22:59
你有没有将 Ngzone 导入到你的组件中?
2021-05-12 16:22:59
我只是按照你的步骤结束了Cannot read property 'zone' of undefined这发生ClickEventhome.cshtml我的函数看起来像<script> function ClickEvent() { window.angularComponentReference.zone.run(() => { window.angularComponentReference.component.ClickEvents(); }); } </script> ps:在开发者控制台中它工作正常。
2021-05-15 16:22:59

我正在检查代码,我遇到了可能不需要该区域的情况。它在没有 NgZone 的情况下运行良好。

在组件构造函数中这样做:

constructor(....) {
   window['fncIdentifierCompRef'] = {
      component  = 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>

这对我有用。

问题是 Angular 的组件被转译为不像常规 JavaScript 代码那样容易访问的module。访问module功能的过程取决于module的格式。

Angular2 类可以包含无需实例化新对象即可定义的静态成员。您可能希望将代码更改为以下内容:

@component({...})
class MyTest {
    private static text: string = '';
    public static setText(text:string) {
        this.text = text;
    }
}
默认情况下无法访问通过 systemjs 加载的组件,查看转译的 js 也无济于事,因为 js 正在使用 system.register 加载。Angular(或 angular 等)甚至在全局范围内都不可用(stackoverflow.com/questions/34779126/...),我们不会在生产中使用 systemjs。
2021-04-17 16:22:59
要访问 Angular 之外的组件,您应该查看转换后的 JavaScript。通常,网页加载通过访问加载器组件(参见System.importSystemJS)。
2021-05-11 16:22:59
我是不是还需要一种方法来公开公开组件?
2021-05-13 16:22:59

超级简单的解决方案!!使用外部别名保存组件或函数

declare var exposedFunction;
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
    constructor(public service:MyService){
    exposedFunction = service.myFunction;
}

在 index.html 中添加头部

<script>
    var exposedFunction;
</script>

内部暴露的函数不要使用这个。如果需要参数,则必须使用闭包才能使其工作

这在 ionic 中特别有用,可以在网络而不是设备上测试设备通知

以同样的方式,只需将其添加到您的网络文件 @MohammadRezaMrg、index.html 和您公开的函数中
2021-04-26 16:22:59
那么如何从android调用它?
2021-04-27 16:22:59