Sup*_*aca 10 javascript design-patterns mediator publish-subscribe angularjs
到目前为止,我已经看到了许多问题的解决方案.最简单的是,当然,对$emit一个事件中$rootScope作为事件总线例如(https://github.com/btilford/anti-patterns/blob/master/angular/Angular.md)
angular.module('myModule').directive('directiveA', function($rootScope) {
return {
link : function($scope, $element) {
$element.on('click', function(event) {
$rootScope.$emit('directiveA:clicked', event);
});
}
}
});
angular.module('myModule').directive('directiveB', function() {
return {
link : function($scope, $element) {
$rootScope.on('directiveA:clicked', function(event) {
console.log('received click event from directiveA');
});
}
}
});
Run Code Online (Sandbox Code Playgroud)
另一个是使用中介或pubsub功能/封闭范围声明服务,例如(在多个控制器和指令之间进行通信.)
module.factory('MessageService',
function() {
var MessageService = {};
var listeners = {};
var count = 0;
MessageService.registerListener = function(listener) {
listeners[count] = listener;
count++;
return (function(currentCount) {
return function() {
delete listeners[currentCount];
}
})(count);
}
MessageService.broadcastMessage = function(message) {
var keys = Object.keys(listeners);
for (var i = 0; i < keys.length; i++) {
listeners[keys[i]](message);
}
}
return MessageService;
}
);
Run Code Online (Sandbox Code Playgroud)
问题是:
hon*_*n2a 15
在编写AngularJS应用程序时,创建自己的事件发射器实现会产生反作用.Angular已经提供了基于事件的通信所需的所有工具.
$emiton $rootScope可以很好地进行全局的服务间通信,并没有任何缺点.$broadcast在自然范围(一个绑定到您的DOM的一部分)提供了作用域视图分量(指令,控制器)之间的通信.$broadcaston $rootScope将前两个点组合在一起(它提供了一个完全全球化的通信平台).这是基本上由任何基于AngularJS的库使用的解决方案.和
$rootScope.$new(true))并$broadcast在其上使用来轻松创建一个.(然后,您可以将其包装到服务中并将其注入任何您想要的位置.)最后一个选项创建了一个集成到Angular中的完整事件发射器(您的问题中提供的实现至少需要包含所有侦听器调用$apply()以正确集成),如果适合特定用途,可以另外用于数据更改观察-案件.
但是,除非你的应用程序非常庞大,或者你对事件名称冲突真的很偏执,否则前三个选项就足够了.
我不会详细介绍组件之间的其他通信方式.一般来说,当情况需要使用范围,控制器的直接交互或通过DOM节点属性进行通信来进行数据共享时,您应该知道它.
Víť*_*.cz 10
我会说广播是一种Angular方式如何实现这一目标.
但是你的中介可以工作,如果你传递指令的内部功能,例如我在范围内使用了方法,但也可以用控制器方法完成.
我发布时使用了完全相同的工厂.
angular.module("sharedService", [])
.factory('MessageService',
function() {
var MessageService = {};
var listeners = {};
var count = 0;
MessageService.registerListener = function(listener) {
listeners[count] = listener;
count++;
return (function(currentCount) {
return function() {
delete listeners[currentCount];
};
})(count);
};
MessageService.broadcastMessage = function(message) {
var keys = Object.keys(listeners);
for (var i = 0; i < keys.length; i++) {
listeners[keys[i]](message);
}
};
return MessageService;
}
)
.directive("directiveA", function(MessageService) {
return {
link:function(scope) {
scope.click = function() {
MessageService.broadcastMessage("broadcasted message");
};
},
template: '<button ng-click="click()">Click</button>'
};
})
.directive("directiveB", function(MessageService) {
return {
link:function(scope) {
scope.callback = function(message) {
console.log(message);
};
MessageService.registerListener(scope.callback);
}
};
});
Run Code Online (Sandbox Code Playgroud)
完整示例:http://jsbin.com/mobifuketi/1/edit?html,js,console,output
为了完成,我想补充一点,角度也提供了更多的可能性,指令如何沟通.
需要属性
如果您的指令在层次结构中连接,那么您可以使用require属性来访问其他指令控制器.对于许多情况来说,这是最好的解决方案.
.directive("directiveA", function() {
return {
require: "^directiveB",
link: function(scope, element, attrs, directiveCtrl) {
scope.click = function() {
directiveCtrl.call();
};
},
template: '<button ng-click="click()">Click</button>'
};
})
.directive("directiveB", function() {
return {
controller :function() {
this.call = function() {
console.log("method has been called");
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
完整示例:http://jsbin.com/turoxikute/1/edit?html,js,console,output
使用$ watch
如果功能依赖于数据而不依赖于操作,那么您将使用$ watch并对存储在共享服务中的给定模型或模型的更改做出反应,它不像监听器,它基本上检查更改.我已将命名方法changeState()和日志"状态已更改"命名为每个人看清楚.
angular.module("sharedService", [])
.service("MediatorService", function() {
this.state = true;
this.changeState = function() {
this.state = !this.state;
};
})
.directive("directiveA", function(MediatorService) {
return {
link:function(scope) {
scope.click = function() {
MediatorService.changeState();
};
},
template: '<button ng-click="click()">Click</button>'
};
})
.directive("directiveB", function(MediatorService) {
return {
link:function(scope) {
scope.mediator = MediatorService;
scope.$watch("mediator.state", function(oldValue, newValue) {
if (oldValue == newValue) {
return;
}
console.log("state changed");
});
}
};
});
Run Code Online (Sandbox Code Playgroud)
完整示例:http://jsbin.com/darefijeto/1/edit?html,js,console,output
| 归档时间: |
|
| 查看次数: |
9067 次 |
| 最近记录: |