首页 文章

Angular 2如何让Angular检测Angular之外的变化?

提问于
浏览
16

我正在尝试创建一个简单的示例项目来测试角度2更改检测机制:我在主索引页面上的脚本标记中创建一个纯javascript对象 . 它包含以下内容:

var Tryout = {};
        Tryout.text = "Original text here";
        Tryout.printme = function(){
            console.log(Tryout.text);
        }
        Tryout.changeme = function(){
            Tryout.text = "Change was made";
        }

一个用于控制台登录的功能,另一个用于更改文本属性 .

现在在Angular 2中,代码如下所示:

import {Component} from "angular2/core"

@Component({
    selector: 'my-app',
    template: `
        <h1>{{TryoutRef.text}}</h1>
        <input type="text" [(ngModel)]="TryoutRef.text">
        <button (click)="consoleLogMe()">Console Log</button>
        <button (click)="changeMe()">Change me inside</button>
    `
})

export class MyApp{

    TryoutRef:any = Tryout;
    constructor(){
    }
    changeMe(){
        this.TryoutRef.changeme();
    }
    consoleLogMe(){
        console.log(this.TryoutRef.text);
    }

}
declare var Tryout:string;

我想要做的是:当我通常使用onclick(完全在角度之外)调用函数Tryout.printme()时,我希望angular检测更改并更新屏幕 .

我成功了这一点:当我从组件调用Tryout.printme()时(changeme()函数调用Tryout.printme()),Angular检测到更改并更新UI,这很好 . 此外,当我从外部角度更改并从Angular调用consoleLogMe()时,它会记录更改的文本并更新UI .

我想我需要在Angular以某种方式运行的同一区域中执行Tryout.changeme() . 有任何想法吗?我有一个很大的项目,它是在纯javascript / jquery中完成的,现在我慢慢地需要将把手模板重写为angular2组件而不触及模型(尚未) . 为此,我需要强制模型在与角度相同的区域中执行 .

如果我想在Angular 1中执行类似的操作,我只需要$ scope . $ apply它可以工作 .

Here is a gif from the example:

enter image description here

1 回答

  • 11

    您可以通过在Angular应用程序中导出 NgZone 来完成此操作 . 通常,你应该在Angular中做所有的事情,但是如果你真的想要从Angular中执行你的逻辑,你需要得到正确的 zone ,正如你所说的那样 .

    这个技巧滥用Angular的依赖注入并挂钩 window 对象上注入的 zone ,如this issue所示 . 声明对 NgZone 的依赖关系,并将其分配给 window.zoneImpl 以进行导出 .

    //our root app component
    import {Component, NgZone} from 'angular2/core'
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          <h2>Hello {{name}}</h2>
    
        </div>
      `,
    })
    export class App {
      constructor(zone: NgZone) {
        this.name = 'Angular2'
        window.app = this
        window.zoneImpl = zone
      }
    }
    

    在Angular bootstrapping之后,你应该有一个 zoneImpl 全局变量 . 您可以使用 run 方法关闭Angular .

    zoneImpl.run(() => window.app.name = "new name!")

    Live demo.

相关问题