当前位置: 首页 > 面试题库 >

AngularJS 1.5+组件不支持Watchers,如何解决?

程天佑
2023-03-14
问题内容

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

问题答案:

在没有观察者的情况下编写组件

该答案概述了在不使用观察程序的情况下用于编写AngularJS
1.5组件的五种技术。

  • 使用ng-change指令
  • 使用$onChanges生命周期挂钩
  • 使用$doCheck生命周期挂钩
  • 组件间通信与需求
  • 使用RxJS从服务推送值

使用ng-change指令

有哪些可选方法可以在不使用watch来准备AngularJs2的情况下观察obj状态的变化?

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

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

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

<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);
});

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

使用$onChanges生命周期挂钩

1.5.3版中 ,AngularJS向服务添加了$onChanges生命周期挂钩$compile

从文档中:

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

  • $
    onChanges(changesObj)-每当单向(<)或插值(@)绑定更新时调用。的changesObj是散列的键是已更改的绑定的属性的名称,和值是以下形式的对象{ currentValue: ..., previousValue:...}。使用此挂钩可触发组件内的更新,例如克隆绑定值,以防止外部值的意外突变。

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

$onChanges钩用于与外部变化引入组分反应<单向绑定。该ng-change指令用于ng- model通过&绑定从组件外部的控制器传播更改。

使用$doCheck生命周期挂钩

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

从文档中:

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

* $doCheck()-在摘要循环的每个回合上调用。提供机会来检测更改并采取措施。您希望对检测到的更改做出响应的任何操作都必须从此挂钩中调用。实现这一点对何时$onChanges调用没有影响。例如,如果您希望执行深度相等检查或检查Date对象,而Angular的更改检测器无法检测到该更改,因此不会触发,则此钩子可能很有用$onChanges。该钩子不带任何参数调用;如果检测到更改,则必须存储以前的值以与当前值进行比较。

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

指令可能需要其他指令的控制器来实现彼此之间的通信。这可以在组件中通过为require属性提供对象映射来实现。对象键指定属性名称,在这些属性名称下,所需的控制器(对象值)将绑定到所需组件的控制器。

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开发人员指南》-组件间通信

使用[RxJS](https://github.com/Reactive-

Extensions/rx.angular.js)从服务推送值

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

使用RxJS Extensions for 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

在上PLNKR DEMO。



 类似资料:
  • 当我运行HelloWorld时,它会返回: “java.lang.UnsupportedClassVersionError:HelloWorld已由java运行时的最新版本(类文件版本52.65535)编译,此版本的java运行时仅识别52.0以下的类文件版本。” 我该如何解决这个问题?

  • Watchers是添加到变量类型的函数,例如原子和引用变量,当变量类型的值发生变化时,它们会被调用。 例如,如果调用程序更改了atom变量的值,并且如果将watcher函数附加到atom变量,则只要原子的值发生更改,就会调用该函数。 Clojure for Watchers提供以下功能。 add-watch 向watch/atom/var/ref引用添加监视功能。 手表'fn'必须是4个参数的'f

  • 我试图强制刷新布局,重启,更新Android Studio,停止杀毒一段时间,但问题仍然在那里。 令人惊讶的是,我能够编译和运行应用程序,但如何摆脱这个错误? 我正在使用: Android Studio 3.5.3 Android SDK工具29.0.2 Android SDK平台Android 10.0(Q)Android SDK平台29 默认OpenJDK平台二进制 要再现错误,请执行以下操作

  • 我使用xampp 32位PHP7.1。1. 我在我的Windows上安装了mongodb 3.4.2(Windows 8 Pro 64位) 我还安装了驱动程序(php_mongodb.dll) 我从这里得到:https://pecl.php.net/package/mongodb/1.2.5/windows (7.1线程安全(TS)x86) 但是,当我的系统执行时,仍然存在错误: 哎呀,好像出了什

  • tooltip 内不支持 router-link 组件,请使用 vm.$router.push 代替。 需求:在el-tooltip内展示自定义组件<mb-image-base64 /> element-ui官网提示如下: tooltip 内不支持 router-link 组件,请使用 vm.$router.push 代替。 显然我目前的写法是不合适的,不能直接将<mb-image-base64

  • 问题内容: 遇到不支持的major.minor版本52.0如何解决? 问题答案: 问题是由于Java版本不匹配。 这些是分配的专业编号。关于不受支持的major.minor版本的错误是因为在编译期间,你在运行时使用的是较高的JDK,而使用的是较低的JDK。 因此,“major.minor版本52.0”错误可能是因为jar是在JDK 1.8中编译的,但是你正在尝试使用JDK 1.7环境运行它。报告的