父级和 子集 controller 之间的通讯
在同个 angular.js 应用的控制器之间进行通信可以有很多种不同的方式,本文主要讲两种:
基于scope继承的方式 基于event传播的方式
基于scope继承的方式
最简单的让控制器之间进行通信的方法是通过scope的继承。假设有两个控制器Parent、Child,Child 在 Parent 内,那Child 可以称为子控制器,它将继承父控制器Parent的scope。这样,Child就可以访问到Parent的scope中的所有函数和变量了。 需要注意的是,由于scope的继承也是基于Js的原型继承,如果变量是基本类型的,那在Child中的修改(写),有可能会导致Parent中的数据变脏
基本类型变量的继承
function Sandcrawler($scope) {
$scope.location = 'Mos Eisley North';
$scope.move = function(newLocation) {
$scope.location = newLocation;
}
}
function Droid($scope) {
$scope.sell = function(newLocation) {
$scope.location = newLocation;
}
}
// html
<div ng-controller="Sandcrawler">
<p>{{location}} </p>
<button ng-click="move('Mos Eisley South')">Move</button>
<div ng-controller="Droid">
<p>{{location}} </p>
<button ng-click="sell('Owen Farm')">Sell</button>
</div>
</div>
看完上面的代码我们知道,location 属性是直接被注册到 $scope 中的,Droid控制器所拥有的scope从Sandcrawler控制器的scope中继承了这个属性并且可以读取它。看以下两个假设场景:
如果 Sandcrawler 中改变了 location 属性,在 Droid 中也会读取到这个改变;在 view 中的表现则是:点击了 Move 按钮的话,两个 p 标签都会显示 Mos Eisley South
反过来,如果 Droid 中对 $scope.location 进行改写,它只改写自己scope中 location 属性的值,它不会影响 Sandcrawler 中的这个属性的值;在 view 中的表现则是:当点击了 Sell 按钮之后,两个控制器scope之间的数据共享就不复存在了,之后无论点多少次 Move 按钮,都影响不了 Droid 中的 p 标签的显示了
经过上面的教训,有时候我们想要达到的效果可能达不到(如点了 Sell 按钮之后再点 Move 还想让它起作用),这样在ng的开发者中逐渐达成了一个一致的约定,千万不要把那些可以被子级scope改写的属性用基础类型直接添加在 $scope 对象上,而是应该尽可能地用对象类型去添加
对象类型变量的继承
通过上面的结论我们知道,可以用对象类型的变量来作为属性添加到 $scope 中去,这样,只要是引用了这个对象的,无论是谁,在哪个控制器里面,对这个对象变量的改写都会影响都所有引用了这个对象的实例。看下面的代码:
<div ng-controller="SandcrawleObject">
<p>Sandcrawler Location: </p>
<p>{{sandcrawler.location }}</p>
<div ng-controller="DroidObject">
<button ng-click="summon('Owen Farm')">
Summon Sandcrawler
</button>
<p>{{sandcrawler.location }}</p>
</div>
</div>
angular.module("communicationApp", [])
.controller("SandcrawleObject",SandcrawleObject)
.controller("DroidObject",DroidObject )
.controller("Sandcrawler", Sandcrawler)
.controller("Droid",Droid ); function Sandcrawler($scope) {
$scope.location = 'Mos Eisley North';
$scope.move = function(newLocation) {
$scope.location = newLocation;
}
} function Droid($scope) {
$scope.sell = function(newLocation) {
$scope.location = newLocation;
}
} function SandcrawleObject($scope) {
$scope.sandcrawler = {
location:'Mos Eisley North'
};
} function DroidObject($scope) {
$scope.summon = function (newLocation) {
$scope.sandcrawler = {
location: newLocation
}
}
}
跑一下上面的代码就知道,当我们使用“召唤术”的时候,可以改写 Sandcrawler 控制下的 p 标签的显示了
基于event传播的方式
基于scope继承的方式只能处理父子级控制器之间的通信问题,不能处理兄弟/相邻控制器之间的通信问题。这时候,我们需要使用基于event传播的方式来进行通信,这里,ng为我们提供了三个方法:$on , $emit , $broadcast ,需要明确的是:这种方法不仅可以处理兄弟scope间的通信问题,对于解决父子scope间的通信也是毫无压力
子–>父:$emit
整个过程是这样的:
- 子scope中的控制器通过 $scope.$emit 触发一个事件向上传播
- 这个事件会经过每一层的父scope,至于处不处理是父scope自己的事情了
- 如果处理,就在想要处理的那个祖先scope中放一个 $scope.$on 监听着就行了
// 父scope上的控制器
function Sandcrawler($scope) {
$scope.location = 'Mos Eisley North';
$scope.$on('summon', function(e, newLocation) {
$scope.location = newLocation;
});
}
// 子scope上的控制器
function Droid($scope) {
$scope.location = 'Owen Farm';
$scope.summon = function() {
$scope.$emit('summon', $scope.location);
}
}
// html
<div ng-controller="Sandcrawler">
<p>Sandcrawler Location: </p>
<div ng-controller="Droid">
<p>Droid Location: </p>
<button ng-click="summon()">Summon Sandcrawler</button>
</div>
</div>
跟我之前写的一篇DOM事件一样,如果你不想让你的事件再往更上层传播,在 $on 中的处理函数调用 e.stopPropagation() 即可
父–>子:$broadcast
接下来的东西就简单了,从父到子,用另外一个方法就是了,同样用 $on 监听着,all done,看下面代码:
// 父scope上的控制器
function Sandcrawler($scope) {
$scope.location = 'Mos Eisley North';
$scope.recall = function() {
$scope.$broadcast('recall', $scope.location);
}
}
// 子scope上的控制器
function Droid($scope) {
$scope.location = 'Owen Farm';
$scope.$on('recall', function(e, newLocation) {
$scope.location = newLocation;
});
}
// html
<div ng-controller="Sandcrawler">
<p>Sandcrawler Location: </p>
<button ng-click="recall()">Recall Droids</button>
<div ng-controller="Droid">
<p>Droid Location: </p>
</div>
</div>
同级之间
拥有同个父scope的子级scope之间,也就是兄弟/相邻scope之间的通信,其实是借助“奶爸”传递消息的:
- 子级scope中有谁想传消息了,$emit 一个给“奶爸”
- 然后通过“奶爸” $broadcast 给所有孩子这个相同的信息,当然发出信息的那个可以选择是否要忽略掉自己发出的信息
// 父scope上的控制器
function Sandcrawler($scope) {
$scope.$on('requestDroidRecall', function(e) {
$scope.$broadcast('executeDroidRecall');
});
}
// 子scope上的控制器
function Droid($scope) {
$scope.location = 'Owen Farm';
$scope.recallAllDroids = function() {
$scope.$emit('requestDroidRecall');
}
$scope.$on('executeDroidRecall', function() {
$scope.location = 'Sandcrawler';
});
}
// html
<div ng-controller="Sandcrawler">
<div ng-controller="Droid">
<h2>R2-D2</h2>
<p>Droid Location: </p>
<button ng-click="recallAddDroids()">Recall All Droids</button>
</div>
<div ng-controller="Droid">
<h2>C-3PO</h2>
<p>Droid Location: </p>
<button ng-click="recallAddDroids()">Recall All Droids</button>
</div>
</div>
上面代码中要注意的是:子scope通过 $emit 发出的事件名不能与父scope用 $broadcast 的事件名一样,如果有传参数,那当然参数可以一样,因为参数就是我们要传的数据。事件名不能一样是为了防止进入死循环。
父级和 子集 controller 之间的通讯的更多相关文章
- jquery 找到指定父级指定子集
其中 closest() : jquery 1.3 新增 从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素. 其中 find() : 搜索所有与指定表达式匹配的元素.这个函数是找出正在处理的元 ...
- javascript父级鼠标移入移出事件中的子集影响父级的处理方法
一.我们先分析其产生的原因: 1.当鼠标从父级移入子集时触发了父级的两个事件:a.父级的mouseout事件(父级离开到子集):b.由于事件冒泡影响,又触发了父级的mouseover事件(父级移入父级 ...
- angularJS的controller之间如何正确的通信
AngularJS中的controller是个函数,用来向视图的作用域($scope)添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为. 当我们在创建新的控制器时,angularJ ...
- controller 和 指令 通讯方法
在 angular 中我们经常会使用多个 controller 和 指令 他们拥有各自的 $scope , 这就产生了跨$scope调用的问题. 有几种常见的方法来可以使用. 方法一 : 指令 req ...
- angular controller 之间的通信方式
AngularJS中的controller是个函数,用来向视图的作用域($scope)添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为. 当我们在创建新的控制器时,angularJ ...
- Angular10 组件之间的通讯
1 父组件和子组件之间的通讯 2 利用中间组件实现两个组件之间的通讯 3 利用服务实现两个组件之间的通讯 2017年8月26日20:09:13 待更新... 1 组件之间的关系图 1.1 父子关系 1 ...
- 通过$broadcast或$emit在子级和父级controller之间进行值传递
通过$broadcast或$emit在controller之间进行值传递,不过这些controller必须是子级或者父级关系, $emit只能向父级parent controller传递事件event ...
- angularJs 自定义指令传值---父级与子级之间的通信
angularJs自定义指令用法我忽略,之前有写过,这里只说一下父子级之间如何传值: 例如: 模块我定义为myApp,index.html定义 <my-html bol-val="bo ...
- angularjs中父,子,兄之间controller值得传递
使用angularjs,发现controller间的值传递,比较麻烦的,以后几篇文章会陆续说几种方法. 一,angularjs $broadcast $emit $on的处理思想 在一个control ...
随机推荐
- appium+python自动化26-模拟手势点击坐标(tap)
# 前言: 有时候定位元素的时候,你使出了十八班武艺还是定位不到,怎么办呢?(面试经常会问) 那就拿出绝招:点元素所在位置的坐标 tap用法 1.tap是模拟手指点击,一般页面上元素 的语法有两个参 ...
- Combogrid的onChange和onSelect
这里只作记录一下 在easyui开发过程中遇到下边两个事儿 combogrid/combotree做级联: $("#" + deptId).combotree( { url : u ...
- cocos2d-x v3.0各个环境下创建项目以及编译、执行官方DEMO
摘自:https://github.com/cocos2d/cocos2d-x/ 怎样创建一个新项目 How to start a new game Download the code from co ...
- Windows2003 Webshell默认权限
0×00 前言 0×01 Windows2003默认配置 0×02 Windows2003典型配置的权限 0×03 cmd运行的条件 0×00 前言 这一章主要讲解关于我们刚拿到webshell的 ...
- 微软URLRewriter.dll的url重写的简单使用(实现伪静态)
先添加引用URLRewriter.dll到项目下的bin目录中,下载: http://files.cnblogs.com/tianguook/URLRewriter.rar 1.在web.config ...
- 《纵向切入ASP.NET 3.5控件和组件开发技术》笔记:高效率事件集合对象
在之前讲的几个例子中,使用的是最普通的定义事件方法,比如KingTextBox中事件是这样定义的:/// <summary>/// 获得本书更多内容,请看:/// http://blog. ...
- shiro 授权介绍
授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限.如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等. 一.授权的三要素 授权有着三个 ...
- [Grunt] Watch && grunt-contrib-watch
Watch is an essential component of any Grunt build, and you will find yourself using it in almost ev ...
- (linux shell)第二章--命令之乐(一)
文章来自于我的个人博客:(linux shell)第二章--命令之乐(一) 上一章我们描写叙述了一些linux shell中须要注意的一些语法.接下来我们開始了解linux shell的经常使用 ...
- 【Caffe代码解析】Layer网络层
Layer 功能: 是全部的网络层的基类,当中.定义了一些通用的接口,比方前馈.反馈.reshape,setup等. #ifndef CAFFE_LAYER_H_ #define CAFFE_LAYE ...