[AngularJS]-多scope之间的通讯
[AngularJS]-多scope之间的通讯
Laughing_Vzr 发表于2年前
[AngularJS]-多scope之间的通讯
  • 发表于 2年前
  • 阅读 2878
  • 收藏 77
  • 点赞 3
  • 评论 20

华为云·免费上云实践>>>   

摘要: 关于scope之间数据通讯和数据共享的方式有很多,例如,在rootScope中添加全局的变量、使用service或factory保存暂存在其中等... 本文介绍到的方法将使用scope的$emit方法与$on方法以事件监听的方式实现scope之间的通讯

关于scope之间数据通讯和数据共享的方式有很多,例如,在rootScope中添加全局的变量、使用service或factory保存暂存在其中等...

下面介绍到的方法将使用scope的**$emit方法与$on**方法,

该实现是以发布/订阅的方式实现scope之间通讯的。

首先来了解下scope的$emit方法与$on方法:

$emit(name, args):

> Dispatches an event name upwards through the scope hierarchy notifying the registered $rootScope.Scope listeners.

根据官方给出的解释,该方法通过rootScope中对注册监听该事件的scope进行通知,也就是说只要监听了该emit事件并且在现有的rootScope域中存活的scope都可以得到该通知。

$on(name, listener):

> Listens on events of a given type.

其中listener的类型是一个方法,可以接收该事件与事件中传递的可变长度参数,并可在方法内进行自定义的操作。

那么我们就通过这种scope域的这两种方法来实现多scope的通讯(消息发布/订阅的方式)。

代码如下:

1.factory声明

/*-----通用发布/订阅器(消息总线)------*/
app.factory('msgBus', ['$rootScope', function($rootScope) {
    var msgBus = {};
    msgBus.emitMsg = function(msg, data) {
        data = data || {};
        // 向上游rootScope中所有监听该事件的scope发出该事件
        $rootScope.$emit(msg, data);
    };
    msgBus.onMsg = function(msg, func, scope) {
        var unbind = $rootScope.$on(msg, func);
        // 当所指定的scope存在(即在scope生命周期之内)时,监听销毁事件并执行传入的func操作
        if (scope) {
            // 这里要这么做的目的是因为如果清除该事件则在跳转到其它scope时该事件一直会被触发
            scope.$on('$destroy', unbind);
        }
    };
    return msgBus;
}]);

2.使用方法

// ps:注意在你的controller中一定要注入该factory

// 发布消息
msgBus.emitMsg('msg','Hello World');

// 监听消息
msgBus.onMsg('msg',function(event,data){
    console.log(data);
    // 或其它操作
},scope);

3.实现效果以及使用场景

假如当点击某scope域中的某个按钮时获取一些数据并将这些数据在另外一个scope域中进行显示,这种情况下就可以在接收数据的域对要发布的事件进行监听(这里要注意监听的事件名称一定要与要发布的事件名称一致);实现的效果就是当点击按钮获取到数据后,监听的区域就可以获得该数据。

** 注:如有其它疑问请在文章后留言**

共有 人打赏支持
粉丝 9
博文 30
码字总数 4712
评论 (20)
qiuss
123
小小黄鸡
13
Laughing_Vzr

引用来自“qiuss”的评论

123
能把疑问说具体一点么?
angyr
这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
手绘灿烂
13 哎呀 趁火之前赶紧留名
萌萌哒丶

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
你在js里面会随便写全局变量吗
发飙的萝卜
struts3
Aric_Chen

引用来自“萌萌哒丶”的评论

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
你在js里面会随便写全局变量吗

这个我不得不说下,不要误导用户。当然没有任何攻击的意思,请谅解。angularjs本身就有依赖注入功能,所有的依赖通过注入,已经没有全局变量的概念了! 我们在js中避免使用全局变量的主要原因是命名污染,可在angularjs中已经不需要考虑这个问题了。文中也样封装,完全有点画蛇添足了!
npmer
msgBus.onMsg 的实现看不太懂。
直接给传入的scope调用$on 不是更直截了当吗?
YueZheng
并不是任意scope之间都可以使用$emit传输数据,需要是子级scope向父级scope $emit,父级使用$on 来接收。由父级向子级传送数据可以使用$broadcast,使用方式和$emit类似。在1.3版本之前应该都是这样,后续新版中还不了解。
Laughing_Vzr

引用来自“Entory”的评论

msgBus.onMsg 的实现看不太懂。
直接给传入的scope调用$on 不是更直截了当吗?
这里只是为了把scope的向下传播停止掉~如果有嵌套的情况下~这里就停止向下传播了~
Laughing_Vzr

引用来自“Aric_Chen”的评论

引用来自“萌萌哒丶”的评论

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
你在js里面会随便写全局变量吗

这个我不得不说下,不要误导用户。当然没有任何攻击的意思,请谅解。angularjs本身就有依赖注入功能,所有的依赖通过注入,已经没有全局变量的概念了! 我们在js中避免使用全局变量的主要原因是命名污染,可在angularjs中已经不需要考虑这个问题了。文中也样封装,完全有点画蛇添足了!
ng官方还是不推荐使用全局变量的,如果使用也需要用户来关注变量声明周期的问题。
Laughing_Vzr

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
是的~你说的也是可行的~但是防止事件继续向下传播~可能就要你每次都单独写一下了~ng是以scope继承的方式来实现的~这个你应该比我清楚吧?
Laughing_Vzr

引用来自“YueZheng”的评论

并不是任意scope之间都可以使用$emit传输数据,需要是子级scope向父级scope $emit,父级使用$on 来接收。由父级向子级传送数据可以使用$broadcast,使用方式和$emit类似。在1.3版本之前应该都是这样,后续新版中还不了解。
是的~$emit是冒泡向上的~所以这里使用rootScope就没有所谓的父级了~加之因为ng的继承~子级都是可以得到该事件的。
大漠穷秋
scope是一个tree形结构,两个同级scope之间传递数据的话,还是直接从rootScope走吧,确实比较直观,就像大家用jQuery的时候直接在body标签上派发事件一样嘛3
Laughing_Vzr

引用来自“大漠穷秋”的评论

scope是一个tree形结构,两个同级scope之间传递数据的话,还是直接从rootScope走吧,确实比较直观,就像大家用jQuery的时候直接在body标签上派发事件一样嘛3
好的~谢大漠指教~
萌萌哒丶

引用来自“Aric_Chen”的评论

引用来自“萌萌哒丶”的评论

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入
你在js里面会随便写全局变量吗

这个我不得不说下,不要误导用户。当然没有任何攻击的意思,请谅解。angularjs本身就有依赖注入功能,所有的依赖通过注入,已经没有全局变量的概念了! 我们在js中避免使用全局变量的主要原因是命名污染,可在angularjs中已经不需要考虑这个问题了。文中也样封装,完全有点画蛇添足了!
那还要scope干嘛,全扔rootScope算了;虽然没有全局的概念,但是rootScope东西多了不会影响性能 ?看看国外论坛上的best practice,全是这样封装的好不
wyysf

引用来自“Entory”的评论

msgBus.onMsg 的实现看不太懂。
直接给传入的scope调用$on 不是更直截了当吗?

引用来自“Laughing_Vzr”的评论

这里只是为了把scope的向下传播停止掉~如果有嵌套的情况下~这里就停止向下传播了~
这个是个公共的发布订阅的封装,向上是$emit向下是$brodcast ,这个由于使用的$rootScope 就可以不用向下,可以变得更高效些
angyr

引用来自“angyr”的评论

这不扯吗?
为什么不直接$rootScope.$emit $rootScope.$on
$rootScope可以随意注入

引用来自“萌萌哒丶”的评论

你在js里面会随便写全局变量吗
这和全局变量有什么关系?他的这种方式明显就是重复封装,$rootscope就是干这事的 这叫随便写全局变量?
竹隐江南
这个,网络稍微不好就有可能在新的scope中接不到数据。
比如第二个scope进入就是加载列表,有时候就收不到数据,我都是直接在第二个scope中订一个方法,在第一个scope中调用传参。血的教训
×
Laughing_Vzr
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: