Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / Angular中用代理服务实现控制器与指令之间的通信

场景

一般来说,angular中,控制器与指令之间的通信可以通过共享作用域的方式来实现。这种处理方式可以满足大部分需求,但是比如说指令如果是独立作用域的话这种情况就玩不转了~在开发中就碰到这样一种尴尬的情况:控制器想要操作某个dom元素(滚动或者获取元素坐标),angular中是不提倡在控制器中直接操作dom而是在指令中。这个时候就可以通过一个代理服务来实现。

代理服务

这一段代理服务的代码短小精悍,从著名的ionic中拷贝出来。
大致思路是通过angular.DelegateService来返回一个代理服务,指令将接口注册到代理服务,控制器调用代理服务中的接口即可操作指令从而操作dom元素。

扩展Angular属性

1
2
3
4
5
6
7
angular.DelegateService = function (methodNames) {
//...
return ["$log", function ($log) {
//...
return new DelegateService();
}];
};
angular中最全局的全局变量当然就是angular了,在此之上添加函数,就可以在模块定义的时候使用。这个函数返回的是标准的声明service的数组,前面一个$log服务,后面一个实现函数。而这个服务本身就是新创建的DelegateService实例。
先来看看这个methodNames参数有什么用处。methodNames看名字就可以知道这是一个数组,包含了一些函数的名称(字符串)。
1
2
3
if (methodNames.indexOf("$getByHandle") > -1) {
throw new Error("Method "$getByHandle" is implicitly added to each delegate service. Do not list it as a method.");
}
 避免内置函数$getByHandle和自定义的函数冲突。
1
2
3
methodNames.forEach(function (methodName) {
DelegateInstance.prototype[methodName] = instanceMethodCaller(methodName);
});
 将所数组中的函数一个个复制到代理服务的原型prototype上。
再来看看如何调用实例函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function instanceMethodCaller(methodName) {
return function caller() {
var handle = this.handle,
args = arguments,
foundInstancesCount = 0,
returnValue;
this._instances.forEach(function (instance) {
if ((!handle || handle === instance.$$delegateHandle) && instance.$$filterFn(instance)) {
foundInstancesCount++;
var ret = instance[methodName].apply(instance, args);
if (foundInstancesCount === 1) {
returnValue = ret;
}
}
});
if (!foundInstancesCount && handle) {
return $log.warn("Delegate for handle "" + handle + "" could not find a " + "corresponding element with id/delegate="" + handle + ""! " + methodName + "() was not called! " + "Possible cause: If you are calling " + methodName + "() immediately, and " + "your element with delegate-handle="" + handle + "" is a child of your " + "controller, then your element may not be compiled yet. Put a $timeout " + "around your call to " + methodName + "() and try again.");
}
return returnValue;
};
}
 其实很简单,这里返回了一个caller函数,这个函数就是遍历_instances中的实例,然后匹配函数名称,调用并返回结果。默认返回第一个实例或者指定的实例。下面来看看这个实例。

代理服务实例

1
2
3
4
function DelegateInstance(instances, handle) {
this._instances = instances;
this.handle = handle;
}
这是一个代理服务,自然会有很多实例,这里用_instances这个数组来保存实例。至于handle可以理解为实例id。
1DelegateService.prototype = DelegateInstance.prototype;
 这里首先将DelegateInstance的原型复制到DelegateService上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function trueFn() {
return true;
}
DelegateService.prototype._registerInstance = function (instance, handle, filterFn) {
var instances = this._instances;
instance.$$delegateHandle = handle;
instance.$$filterFn = filterFn || trueFn;
instances.push(instance);
return function deregister() {
var index = instances.indexOf(instance);
if (index !== -1) {
instances.splice(index, 1);
}
};
};
 这里在代理服务DelegateService的原型上声明了一个函数_registerInstance用来注册服务。该函数将服务保存在代理服务中,同时返回一个注销服务的函数。filterFn实际上就是一个过滤函数,如果实例中拥有私有函数,可以通过自定义过滤函数,只暴露公有函数。
1
2
3
DelegateService.prototype.$getByHandle = function (handle) {
return new DelegateInstance(this._instances, handle);
};
 私有函数,通过handle这个id来获取实例。

使用实例

这里的例子是控制器通过代理服务来操作指令的例子

编写指令,注册服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
angular.module("directive", []).directive("keyboard", ["keyboardService", function (keyboardService) {
return {
replace: true,
templateUrl: "template/keyboard.html",
link: function (scope, elm, attrs) {
var instance = {
toggle: function (flag) {
window.console.log(flag);
}
};
keyboardService._registerInstance(instance);
}
};
}]).service("keyboardService", angular.DelegateService(["toggle"]));

控制器中通过服务调用指令

1
2
3
angular.module("app", ["directive"]).controller("ctrl", ["$scope", "keyboardService", function($scope, keyboardService){
keyboardService.toggle(true);
}]);

代理服务源码

https://github.com/driftyco/ionic/blob/master/js/utils/delegateService.js一些AngularJS相关文章链接:AngularJS权威教程 清晰PDF版  http://www.linuxidc.com/Linux/2015-01/111429.htm希望你喜欢,并分享我的工作~带你走近AngularJS系列
  1. 带你走近AngularJS - 基本功能介绍 http://www.linuxidc.com/Linux/2014-05/102140.htm
  2. 带你走近AngularJS - 体验指令实例 http://www.linuxidc.com/Linux/2014-05/102141.htm
  3. 带你走近AngularJS - 创建自定义指令 http://www.linuxidc.com/Linux/2014-05/102142.htm
如何在 AngularJS 中对控制器进行单元测试 http://www.linuxidc.com/Linux/2013-12/94166.htm在 AngularJS 应用中通过 JSON 文件来设置状态 http://www.linuxidc.com/Linux/2014-07/104083.htmAngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htmAngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交数据 http://www.linuxidc.com/Linux/2014-07/104402.htmAngularJS 的详细介绍:请点这里
AngularJS 的下载地址:请点这里本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-02/128748.htm