本文介绍了AngularJS 1.5+ 组件不支持 Watchers,有什么解决办法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我一直在将我的自定义指令升级到新的组件架构.我读过组件不支持观察者.这样对吗?如果是这样,您如何检测对象的变化?对于一个基本的例子,我有一个自定义组件 myBox
,它有一个子组件 game ,在 game 上有一个绑定.如果游戏组件中有更改游戏,我如何在 myBox 中显示警报消息?我知道有 rxJS 方法是否可以纯粹以角度来做到这一点?我的 JSFiddle
JavaScript
var app = angular.module('myApp', []);app.controller('mainCtrl', function($scope) {$scope.name = "托尼·丹扎";});app.component("myBox", {绑定:{},控制器:函数($element){var myBox = this;myBox.game = '魔兽世界';//如果 myBox.game 发生变化,则显示警告消息 'NAME CHANGE'},controllerAs: 'myBox',templateUrl: "/template",转置:真实})app.component("游戏", {绑定:{游戏:'='},控制器:函数($element){var 游戏 = 这个;},controllerAs: '游戏',templateUrl: "/template2"})
HTML
<script type="text/ng-template" id="/template"><div style='width:40%;border:2px solid black;background-color:yellow'>您最喜欢的游戏是:{{myBox.game}}<game game='myBox.game'></game>
<script type="text/ng-template" id="/template2"><div></br>改变游戏<textarea ng-model='game.game'></textarea>
并且要将事件传播到父组件,需要将事件处理程序添加为子组件的属性.
的组件间通信指令可以要求其他指令的控制器启用彼此之间的通信.这可以通过为 require 属性.对象键指定所需控制器(对象值)将在其下绑定到所需组件的控制器的属性名称.
app.component('myPane', {转置:真实,要求: {tabsCtrl: '^myTabs'},绑定:{标题: '@'},控制器:函数(){this.$onInit = function() {this.tabsCtrl.addPane(this);控制台日志(这个);};},templateUrl: 'my-pane.html'});
有关更多信息,请参阅AngularJS 开发人员指南 - 组件间通信
从服务推送值例如,在您拥有一个保持状态的服务的情况下呢?我如何将更改推送到该服务,以及页面上的其他随机组件是否知道此类更改?最近一直在努力解决这个问题
使用 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 主题 = 新 rx.Subject();var data = "初始";返回 {集:函数集(d){数据 = d;主题.onNext(d);},获取:函数获取(){返回数据;},订阅:功能(o){返回主题.订阅(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 = 函数(){订阅.处置();};});
客户端可以使用 DataService.subscribe
订阅更改,生产者可以使用 DataService.set
推送更改.
PLNKR 上的演示.
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-->
解决方案
Writing Components without Watchers
This answer outlines five techniques to use to write AngularJS 1.5 components without using watchers.
Use the ng-change
Directive
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"
});
And in the parent component:
myBox.gameChange = function(newValue) {
console.log(newValue);
});
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
.
Use the $onChanges
Life-cycle Hook
With version 1.5.3, AngularJS added the $onChanges
life-cycle hook to the $compile
service.
From the Docs:
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.
Use the $doCheck
Life-cycle Hook
With version 1.5.8, AngularJS added the $doCheck
life-cycle hook to the $compile
service.
From the Docs:
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'
});
For more information, see AngularJS Developer Guide - Intercomponent Communicatation
Push Values from a Service with RxJS
Build a service with 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);
}
};
});
Then simply subscribe to the changes.
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();
};
});
Clients can subscribe to changes with DataService.subscribe
and producers can push changes with DataService.set
.
The DEMO on PLNKR.
这篇关于AngularJS 1.5+ 组件不支持 Watchers,有什么解决办法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!