AngularJS 1.5+组件不支持Watchers,如何解决? [英] AngularJS 1.5+ Components do not support Watchers, what is the work around?

本文介绍了AngularJS 1.5+组件不支持Watchers,如何解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在将自定义指令升级到新的组件体系结构.我读过,组件不支持观察者.这样对吗?如果是这样,您如何检测对象的变化?对于一个基本示例,我有一个自定义组件myBox,该组件具有一个子组件游戏,并带有游戏绑定.如果游戏组件中有找零游戏,如何在myBox中显示警告消息?我知道有rxJS方法是否可以纯粹在角度上做到这一点?我的 JSFiddle

I've been upgrading my custom directives to the new component architecture. I've read that components do not support watchers. Is this correct? If so how do you detect changes on an object? For a basic example I have custom component myBox which has a child component game with a binding on the game . If there is a change game within the game component how do I show an alert message within the myBox? I understand there is rxJS method is it possible to do this purely in angular? My JSFiddle

JavaScript

var app = angular.module('myApp', []);
app.controller('mainCtrl', function($scope) {

   $scope.name = "Tony Danza";

});

app.component("myBox",  {
      bindings: {},
      controller: function($element) {
        var myBox = this;
        myBox.game = 'World Of warcraft';
        //IF myBox.game changes, show alert message 'NAME CHANGE'
      },
      controllerAs: 'myBox',
      templateUrl: "/template",
      transclude: true
})
app.component("game",  {
      bindings: {game:'='},
      controller: function($element) {
        var game = this;


      },
      controllerAs: 'game',
      templateUrl: "/template2"
})

HTML

<div ng-app="myApp" ng-controller="mainCtrl">
  <script type="text/ng-template" id="/template">
    <div style='width:40%;border:2px solid black;background-color:yellow'>
      Your Favourite game is: {{myBox.game}}
      <game game='myBox.game'></game>
    </div>
  </script>

 <script type="text/ng-template" id="/template2">
    <div>
    </br>
        Change Game
      <textarea ng-model='game.game'></textarea>
    </div>
  </script>

  Hi {{name}}
  <my-box>

  </my-box>

</div><!--end app-->

推荐答案

没有观察者

此答案概述了用于在不使用

  • 使用 ng-change指令
  • 使用 $onChanges生命周期钩子
  • 使用 $doCheck生命周期钩子
  • 要求
  • 的组件间通信
  • 使用 RxJS
  • 从服务中推送值
    • Use the ng-change Directive
    • Use the $onChanges Life-cycle Hook
    • Use the $doCheck Life-cycle Hook
    • Intercomponent Communication with require
    • Push Values from a Service with RxJS

    不使用watch来准备AngularJs2,有哪些alt方法可用来观察obj状态变化?

    what alt methods available to observe obj state changes without using watch in preparation for AngularJs2?

    您可以使用ng-change指令来响应输入更改.

    You can use the ng-change directive to react to input changes.

    <textarea ng-model='game.game' 
              ng-change="game.textChange(game.game)">
    </textarea>
    

    并且要将事件传播到父组件,需要将事件处理程序添加为子组件的属性.

    And to propagate the event to a parent component, the event handler needs to be added as an attribute of the child component.

    <game game='myBox.game' game-change='myBox.gameChange($value)'></game>
    

    JS

    app.component("game",  {
          bindings: {game:'=',
                     gameChange: '&'},
          controller: function() {
            var game = this;
            game.textChange = function (value) {
                game.gameChange({$value: value});
            });
    
          },
          controllerAs: 'game',
          templateUrl: "/template2"
    });
    

    在父组件中:

    myBox.gameChange = function(newValue) {
        console.log(newValue);
    });
    

    这是以后的首选方法.使用$watch的AngularJS策略是不可扩展的,因为它是一种轮询策略.当$watch侦听器的数量达到2000左右时,UI会变慢. Angular 2中的策略是使框架更具响应性,并避免将$watch放在$scope上.

    This is the preferred method going forward. The AngularJS strategy of using $watch is not scalable because it is a polling strategy. When the number of $watch listeners reaches around 2000, the UI gets sluggish. The strategy in Angular 2 is to make the framework more reactive and avoid placing $watch on $scope.

    使用版本1.5.3 ,AngularJS在$compile服务中添加了$onChanges生命周期挂钩.

    With version 1.5.3, AngularJS added the $onChanges life-cycle hook to the $compile service.

    从文档中:

    控制器可以提供以下用作生命周期挂钩的方法:

    The controller can provide the following methods that act as life-cycle hooks:

    • $ onChanges(changesObj)-每当单向(<)或插值(@)绑定更新时调用. changesObj是一个哈希,其键是已更改的绑定属性的名称,而值是格式为{ currentValue: ..., previousValue: ... }的对象.使用此挂钩可触发组件内的更新,例如克隆绑定值,以防止外部值的意外突变.
    • $onChanges(changesObj) - Called whenever one-way (<) or interpolation (@) bindings are updated. The changesObj is a hash whose keys are the names of the bound properties that have changed, and the values are an object of the form { currentValue: ..., previousValue: ... }. Use this hook to trigger updates within a component such as cloning the bound value to prevent accidental mutation of the outer value.

    — AngularJS综合指令API参考-生命周期钩子

    $onChanges钩子用于对具有<单向绑定的组件中的外部更改做出反应. ng-change指令用于通过&绑定从组件外部的ng-model控制器传播更改.

    The $onChanges hook is used to react to external changes into the component with < one-way bindings. The ng-change directive is used to propogate changes from the ng-model controller outside the component with & bindings.

    版本1.5.8 中,AngularJS在$compile服务中添加了$doCheck生命周期挂钩.

    With version 1.5.8, AngularJS added the $doCheck life-cycle hook to the $compile service.

    从文档中:

    控制器可以提供以下用作生命周期挂钩的方法:

    The controller can provide the following methods that act as life-cycle hooks:

    • $doCheck()-在摘要循环的每一回合调用.提供机会来检测更改并采取措施.您希望对检测到的更改做出响应的任何操作都必须从此挂钩中调用;实现此功能对$onChanges的调用时间没有影响.例如,如果您希望执行深度相等性检查或检查Date对象,而Angular的更改检测器无法检测到该更改,因此不会触发$onChanges,则此钩子可能很有用.该钩子不带任何参数被调用.如果检测到更改,则必须存储以前的值以便与当前值进行比较.
    • $doCheck() - Called on each turn of the digest cycle. Provides an opportunity to detect and act on changes. Any actions that you wish to take in response to the changes that you detect must be invoked from this hook; implementing this has no effect on when $onChanges is called. For example, this hook could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not be detected by Angular's change detector and thus not trigger $onChanges. This hook is invoked with no arguments; if detecting changes, you must store the previous value(s) for comparison to the current values.

    — AngularJS综合指令API参考-生命周期钩子


    require

    的组件间通信

    指令可以要求其他指令的控制器来启用彼此之间的通信.通过在 require 属性.对象键指定属性名称,在这些属性名称下,所需的控制器(对象值)将绑定到所需组件的控制器.


    Intercomponent Communication with require

    Directives can require the controllers of other directives to enable communication between each other. This can be achieved in a component by providing an object mapping for the require property. The object keys specify the property names under which the required controllers (object values) will be bound to the requiring component's controller.

    app.component('myPane', {
      transclude: true,
      require: {
        tabsCtrl: '^myTabs'
      },
      bindings: {
        title: '@'
      },
      controller: function() {
        this.$onInit = function() {
          this.tabsCtrl.addPane(this);
          console.log(this);
        };
      },
      templateUrl: 'my-pane.html'
    });
    

    有关更多信息,请参见 AngularJS开发人员指南-组件间的通讯

    For more information, see AngularJS Developer Guide - Intercomponent Communicatation

    例如,在您拥有处于保持状态的服务的情况下,该怎么办?我如何将更改推送到该服务,页面上的其他随机组件会意识到这种更改?最近一直在努力解决这个问题

    What about in a situation where you have a Service that's holding state for example. How could I push changes to that Service, and other random components on the page be aware of such a change? Been struggling with tackling this problem lately

    使用 RxJS Angular扩展构建服务.

    <script src="//unpkg.com/angular/angular.js"></script>
    <script src="//unpkg.com/rx/dist/rx.all.js"></script>
    <script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
    

    var app = angular.module('myApp', ['rx']);
    
    app.factory("DataService", function(rx) {
      var subject = new rx.Subject(); 
      var data = "Initial";
    
      return {
          set: function set(d){
            data = d;
            subject.onNext(d);
          },
          get: function get() {
            return data;
          },
          subscribe: function (o) {
             return subject.subscribe(o);
          }
      };
    });
    

    然后只需订阅更改.

    app.controller('displayCtrl', function(DataService) {
      var $ctrl = this;
    
      $ctrl.data = DataService.get();
      var subscription = DataService.subscribe(function onNext(d) {
          $ctrl.data = d;
      });
    
      this.$onDestroy = function() {
          subscription.dispose();
      };
    });
    

    客户可以使用DataService.subscribe订阅更改,而生产者可以使用DataService.set推送更改.

    Clients can subscribe to changes with DataService.subscribe and producers can push changes with DataService.set.

    PLNKR上的演示.

    这篇关于AngularJS 1.5+组件不支持Watchers,如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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