一. 作用域继承实现通信
先看一组代码:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"/>
<title>标题</title>
</head>
<body ng-app="test">
<div ng-controller="parentCtrl">
parent: <input ng-model="user.content" />
<div ng-controller="childCtrl">
child: <input ng-model="user.content" />
<button ng-click="initClick()">init</button>
</div>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script>
angular.module('test',[])
.controller('parentCtrl', parentCtrl)
.controller('childCtrl', childCtrl);
function parentCtrl($scope){
$scope.user = {content: 'content'};
$scope.init = function(){
$scope.user.content = 'init';
}
}
function childCtrl($scope){
$scope.initClick = function(){
$scope.init();
}
}
</script>
</body>
</html>
结论:改变父作用域下的模型,子作用域下的模型也会改变;点击子作用域下按钮,同样可以触发父作用域下controller定义的方法;
前提:子作用域下controller不能定义同样的方法或模型,否则会覆盖上层作用域;
缺点:不能用在复杂情况;不易维护;
作用域详解:https://blog.csdn.net/lizhongyang21/article/details/103120292
二. $rootScope
$rootScope 是特殊的作用域继承实现通信的方式;
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"/>
<title>标题</title>
</head>
<body ng-app="test">
<div ng-controller="parentCtrl">
parent: <span ng-bind="user.name"></span>
<div ng-controller="childCtrl">
child: <span ng-bind="user.name"></span><br>
<button ng-click="initClick()">init</button>
</div>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script>
angular.module('test',[])
.controller('parentCtrl', parentCtrl)
.controller('childCtrl', childCtrl);
function parentCtrl($scope, $rootScope){
$rootScope.user = {
name: 'parent'
};
}
function childCtrl($scope, $rootScope){
$scope.initClick = function(){
$rootScope.user = {
name: 'child'
};
}
}
</script>
</body>
</html>
适用:不经常改变,但是许多页面需要使用的数据。如:用户的信息,用户的权限等;
三. $emit, $on, $broadcast
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"/>
<title>标题</title>
</head>
<body ng-app="test">
<div ng-controller="parentCtrl">
<div ng-controller="childCtrl1">
child1: <span ng-bind="name"></span><br>
</div>
<div ng-controller="childCtrl2">
child2: <span ng-bind="name"></span><br>
<button ng-click="initClick()">child2Click</button>
</div>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script>
angular.module('test',[])
.controller('parentCtrl', parentCtrl)
.controller('childCtrl1', childCtrl1)
.controller('childCtrl2', childCtrl2);
function parentCtrl($scope, $rootScope){
$scope.name = 'parent';
//监听事件 + 接收数据
$scope.$on('UPDATE_NAME_CHILD2', function(event , data ){
$scope.$broadcast('UPDATE_NAME_PARENT', data);
});
}
function childCtrl1($scope, $rootScope){
$scope.name = 'child1';
//监听事件 + 接收数据
$scope.$on('UPDATE_NAME_PARENT', function(event , data ){
$scope.name = 'from ' + data.name + ', child1'
});
}
function childCtrl2($scope, $rootScope){
$scope.name = 'child2';
$scope.initClick = function(){
// 冒泡发布
$scope.$emit('UPDATE_NAME_CHILD2', { name: 'child2' });
}
}
</script>
</body>
</html>
注意:(1) $broadcast 会遍历所有子作用域,比较消耗性能;
(2) $on 的回调函数 中$broadcast 事件名称和$on事件名称不能相同,如果相同会造成死循环;
如下,会造成死循环:
$scope.$on('**NAME**', function(event , data ){
$scope.$broadcast('**NAME**', data);
});
四. $emit, $on, $rootScope 实现发布/订阅
说明:$rootScope.$emit('EVENT', {});
形式的发布可以用$rootScope.$on('EVENT', function(){})
接收;
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"/>
<title>标题</title>
</head>
<body ng-app="test">
<div ng-controller="parentCtrl">
<div ng-controller="childCtrl1">
child1: <span ng-bind="name"></span><br>
</div>
<div ng-controller="childCtrl2">
child2: <span ng-bind="name"></span><br>
<button ng-click="initClick()">child2Click</button>
</div>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script>
angular.module('test',[])
.controller('parentCtrl', parentCtrl)
.controller('childCtrl1', childCtrl1)
.controller('childCtrl2', childCtrl2)
.factory('pubSubService', pubSubService);
function parentCtrl(){}
function childCtrl1($scope, $rootScope, pubSubService){
$scope.name = 'child1';
pubSubService.subscribe('NAME_UPDATE',$scope, function(event, data){
$scope.name = data.name;
});
}
function childCtrl2($scope, $rootScope, pubSubService){
$scope.name = 'child2';
$scope.initClick = function(){
pubSubService.publish('NAME_UPDATE', { name: 'I am from child2' });
}
}
// 发布/订阅
function pubSubService($rootScope){
//发布
var publish = function(eventName, data) {
if (!eventName) {
console.log('请输入事件名称');
}
$rootScope.$emit(eventName, data);
};
//订阅
var subscribe = function(eventName, scope, func) {
if (!eventName) {
console.log('请输入事件名称');
}
var unbind = $rootScope.$on(eventName, func);
scope.$on('$destroy', unbind);
};
return {
publish : publish ,
subscribe : subscribe
};
}
</script>
</body>
</html>
https://my.oschina.net/u/2434456/blog/602406
五. 粗暴执行另一作用域下的方法
angular.element(document.getElementById(‘另一个控制器的边界HTML标记 ID’)).scope().方法名();