Angular 2如何让Angular检测Angular之外的变化? [英] Angular 2 How to get Angular to detect changes made outside Angular?

查看:127
本文介绍了Angular 2如何让Angular检测Angular之外的变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  var Tryout = {}; 
Tryout.text =原文在这里;
Tryout.printme = function(){
console.log(Tryout.text);
}
Tryout.changeme = function(){
Tryout.text =改变了;
}

控制台记录它的一个功能,以及一个更改文本属性的功能。 / p>

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

  import {组件}来自angular2 / core

@Component({
选择器:'my-app',
模板:`
< h1> {{TryoutRef .text}}< / h1>
< input type =text[(ngModel)] =TryoutRef.text>
< button(click)=consoleLogMe() >控制台日志< / button>
< button(click)=changeMe()>在里面更改我< / button>
`
})

导出类MyApp {

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

}
声明var Tryout:string;

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



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



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



如果我想在Angular 1中执行类似的操作,我只需$范围。$ apply它会起作用。



以下是示例中的gif:



解决方案

您可以通过导出<您的Angular应用中的code> NgZone 。
通常,你应该在Angular中做所有的事情,但是如果你真的想要从Angular中执行你的逻辑,你需要得到正确的区域,就像你一样已经说过。



这个技巧滥用Angular的依赖注入并挂钩上注入的区域窗口对象,如此问题所示。声明对 NgZone 的依赖,并将其分配给 window.zoneImpl 以便导出。

  //我们的根应用程序组件
import {Component,NgZone}来自'angular2 / core'

@Component({
选择器:'my-app',
模板:`
< div>
< h2> Hello {{name}}< / h2>

< / div>
`,
})
导出类App {
构造函数(区域:NgZone){
this.name ='Angular2 '
window.app =这个
window.zoneImpl = zone
}
}

在Angular引导之后,你应该有一个 zoneImpl 全局变量。您可以使用运行方法关闭Angular。



zoneImpl.run(( )=> window.app.name =新名称!)



现场演示。


I am trying to create a simple example project to test the angular 2 change detection mechanism: I create a pure javascript object in script tags on the main index page. it contains the following:

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

One function to console log it, and one to change the text property.

Now in Angular 2 the code looks like this:

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;

What I am trying to do is this: When I call the function Tryout.printme() normally with onclick (Completely outside of angular) I want angular to detect the change and update the screen.

I succeeded to this point: When I call Tryout.printme() from the component (the changeme() function is calling Tryout.printme()), Angular detects the change and updates the UI which is fine. Also, when I change from outside angular and I call consoleLogMe() from Angular it is logging the changed text and updates the UI.

I guess I need to execute Tryout.changeme() in the same Zone that Angular is running in somehow. Any ideas? I have a big project which is done in pure javascript/jquery, and now I slowly need to rewrite the handlebar templates to angular2 components without touching the model (yet). For that I need to force the model to execute in the same zone as angular.

If I wanted to do something like this in Angular 1 I would just $scope.$apply it would work.

Here is a gif from the example:

解决方案

You can do this by exporting NgZone inside your Angular app. Usually, you should do all things inside Angular, but if you really want to execute your logic out of Angular, you need to get the right zone, as you have said.

This trick is abusing Angular's dependency injection and hooking the injected zone on window object, as this issue shows. Declaring a dependency on NgZone, and assigning it to window.zoneImpl for exporting.

//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
  }
}

After Angular bootstrapping, you should have a zoneImpl global variable. You can use the run method to kick Angular off.

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

Live demo.

这篇关于Angular 2如何让Angular检测Angular之外的变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆