谈一谈JS消息机制和事件机制的理解


Posted in Javascript onApril 14, 2016

消息/事件机制是几乎所有开发语言都有的机制,并不是deviceone的独创,在某些语言称之为消息(Event),有些地方称之为(Message). 其实原理是类似的,只不过有些实现的方式要复杂一点。我们deviceone统一就叫消息.

消息基础概念

还有一些初学者不太熟悉这个机制,我们先简单介绍一些基础概念,如果熟悉的人可以跳过这个部分。
一个/条消息可以理解为是一个数据结构,包含以下几个基本部分:

1.消息源:就是消息的来源,发出这个消息的对象

2.消息名:就是消息的唯一标示

3.消息数据:消息发出后附带的数据,有可能数据是空

消息从种类上又可以分为2种:

1.系统消息:由操作系统或deviceone系统发送出来的消息,消息的名称是固定的。

2.自定义消息:由开发者自己定义,自己发送出来的消息,消息的名字是随意的,可以任意定义。

举例说明:

比如用户点击一个do_Button按钮,就会触发一个系统消息,包含3个部分:

1.消息源:用户点中的button对象

2.消息名:touch

3.消息数据:这个消息没有附带数据

比如用户通过do_Button按钮触发一个自定义事件,包含3个部分:

1.消息源: button对象

2.消息名:用户随便定义,叫aaa,bbb,ccc都可以

3.消息数据:附带的数据由触发消息的时候设定

发布/订阅模式

发布/订阅模式是最常用的设计模式之一,是消息机制的核心,其特点就是降低耦合度,让二个独立的对象不互相依赖。简单介绍一下,熟悉的同学可以跳过。

我们先从现实的一个简单例子来说明这个问题,参考下图:

谈一谈JS消息机制和事件机制的理解

从这个图我们可以看出

1.消费者和出版社互相不认识,消费者不需要了解他想要的杂志是具体哪家出版社出的;出版社也不需要了解具体是哪个人定了他们出版社发行的书。

2.消费者和出版社必须都认识邮局。

3.消费者需要告诉邮局消费者的名字地址以及想要订阅的杂志名字

4.可以多个消费者订阅同一本杂志

5.邮局拿到杂志后,会一一通知消费者,通知的时候同时把杂志送到消费者手里。

看完上面现实例子,我们再来看抽象的描述会更清晰一点,看下图:

谈一谈JS消息机制和事件机制的理解

和上面的实际例子描述一一对应:

1.系统/开发者和函数对象互相不依赖,系统/开发者只管触发一个消息,并不关心谁去接受

2.系统/开发者和函数对象必须能获取到消息源对象

3.函数对象订阅消息的时候需要标示消息的名称和函数对象的引用

4.可以多个函数对象订阅同一个消息源同一名字的消息

5.消息源触发消息会一一通知所有订阅者,并把data数据传递到回调函数对象

看完抽象的描述,我们最后来看实际的deviceone开发的例子,还是以do_Button为例子。

1. 当用户点击一个button,触摸到的时候,系统会获取到button这个对象作为消息源,fire一个”touch”消息,任何订阅了”touch”消息的函数对象都会接收到这个消息并引起函数的执行。

//获取button对象
var btn_hello = ui("btn_hello");
//定义函数对象
function f(){
//当btn_hello这个按钮接收到手指点击就会执行下面的代码
deviceone.print("f 函数接收到点击触发消息")
}
function f(){
//当btn_hello这个按钮接收到手指点击就会执行下面的代码
deviceone.print("f 函数接收到点击触发消息")
}
//f,f订阅button的touch消息
btn_hello.on("touch",f);
btn_hello.on("touch",f);

2. 我们可以为button对象定义2个自定义的消息”message1”和”message2”,分别有2个函数对象订阅这2个消息。但是最后要触发这个消息必须是开发者通过调用fire函数才能触发,这就是和系统消息的区别。

//获取button对象
var btn_hello = ui("btn_hello");
//定义函数对象
function f(d){
//当btn_hello这个按钮接收到开发者触发的消息message就会执行下面的代码
deviceone.print("f 函数接收到message消息,消息的数据是:"+d)
}
function f(d){
//当btn_hello这个按钮接收到开发者触发的消息message就会执行下面的代码
deviceone.print("f 函数接收到message消息,消息的数据是:"+d)
}
//f,f订阅button的touch消息
btn_hello.on("message",f);
btn_hello.on("message",f);
//触发消息
btn_hello.fire("message","data");
btn_hello.fire("message","data");

看到这里,你肯定会奇怪,为什么我们要在button上自定义对象?这有神马意义?其实确实没有意义也没有必要,这里只是拿button举例子,在常规的开发中,基本不会这么用。

消息的使用

前面讲了这么多,现在才是deviceone消息的使用。使用其实很简单,上面的例子基本说明的了系统事件和自定义事件的使用方法。

有几个概念再说明一下

1.deviceone的所有对象,包括UI,MM,SM对象都可以是消息源

// SM对象可以是消息源
var page = sm("do_Page");
page.on("loaded",function()){
// 这个是page对象的系统消息,这个消息不需要手动触发,系统会自动触发
}
page.on("message",function(d)){
// 这个是page对象的自定义消息
}
page.fire("message","data");
// MM对象可以是消息源
var http = mm("do_Http");
http.on("result",function()){
// 这个是http对象的系统消息,这个消息不需要手动触发,接受到http服务端的反馈后会自动触发
}
http.on("message",function(d)){
// 这个是http对象的自定义消息
}
http.fire("message","data");
//UI对象可以是消息源
var alayout = ui("alayout_id");
alayout.on("touch",function()){
// 这个是alayout对象的系统消息,这个消息不需要手动触发,手机点击就会触发
}
alayout.on("message",function(d)){
// 这个是alayout对象的自定义消息
}
alayout.fire("message","data");

2.消息源对象有作用域,所以订阅和触发的消息源必须是是一个作用域的同一个对象。这里结合数据分享和数据传递文档来理解。

看以下的例子,test1.ui和test2.ui有可能在一个page作用域,也有可能不在一个作业域,只有在一个作用域fire的消息才能正确送达回调函数。

判断是否一样,可以通过打印page的地址 page.getAddress().

//在test.ui.js里订阅消息
var page = sm("do_Page");
deviceone.print(page.getAddress());
page.on("message",function(d)){
deviceone.print(d);
}
//在test.ui.js触发消息
var page = sm("do_Page");
deviceone.print(page.getAddress());
page.fire("message","data");

如果不在同一page作用域,则可以把消息订阅在2个page都能共享到的app作用域
上面的代码改成:

//在test.ui.js里订阅消息
var app = sm("do_App");
app.on("message",function(d)){
deviceone.print(d);
}
//在test.ui.js触发消息
var app = sm("do_App");
app.fire("message","data");

3.同样的函数对象可以重复订阅一个对象源的消息,触发消息的时候会使函数执行多次,这是初学者经常犯的错误。

var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("执行次数"+(count++));
}
page.on("message",f);
page.on("message",f);
page.fire("message");

看上面的例子,如果执行的话,会打印2此,因为订阅了2次,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来执行了重复的on函数,实际情况经常是比如在点击事件里执行on函数,每点击一下按钮,就重复订阅一次。

4.消息的订阅一定要在消息的触发之前,这是初学者经常犯的错误。

var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("执行次数"+(count++));
}
page.fire("message");
page.on("message",f);

看上面的例子,如果执行的话,会没有效果,或许你会说谁会写这样的代码?实际情况肯定没有这么容易看出来顺序反了,实际情况经常是比如on函数执行在某一个函数的回调函数里,你无法确定回调函数啥时候执行,是否是在fire之前执行。一般碰到这种情况可以加几个deviceone.print打印一下看看是on先执行还是fire先执行。

5.有订阅就有取消订阅,取消订阅是off函数,之所以很少用,是因为closePage的时候会自动把当前page作用域订阅的消息全部释放。

但是如果消息订阅在app作用域,就要注意,可能需要手动去取消订阅。否则就会出现触发消息的时候会使函数执行多次的问题。

var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("执行次数"+(count++));
}
page.on("message",f);
page.fire("message");
.page.off("message");
page.fire("message");

看上面的例子,打印只会执行一次,因为fire一次后就取消订阅了。

Javascript 相关文章推荐
brook javascript框架介绍
Oct 10 Javascript
JavaScript中的关键字"VAR"使用详解 分享
Jul 31 Javascript
js禁止页面刷新禁止用F5键刷新禁止右键的示例代码
Sep 23 Javascript
jQuery源码解读之removeClass()方法分析
Feb 20 Javascript
Bootstrap每天必学之面板
Nov 30 Javascript
Bootstrap Paginator分页插件使用方法详解
May 30 Javascript
AngularJS中比较两个数组是否相同
Aug 24 Javascript
node中的密码安全(加密)
Sep 17 Javascript
JS中如何轻松遍历对象属性的方式总结
Aug 06 Javascript
浅谈layui框架自带分页和表格重载的接口解析问题
Sep 11 Javascript
微信小程序分享小程序码的生成(带参数)以及参数的获取
Mar 25 Javascript
Vant+postcss-pxtorem 实现浏览器适配功能
Feb 05 Javascript
Kindeditor在线文本编辑器如何过滤HTML
Apr 14 #Javascript
基于RequireJS和JQuery的模块化编程日常问题解析
Apr 14 #Javascript
[原创]JQuery 在表单提交之前修改 提交的值
Apr 14 #Javascript
javaScript数组迭代方法详解
Apr 14 #Javascript
基于JS实现移动端访问PC端页面时跳转到对应的移动端网页
Dec 24 #Javascript
js贪吃蛇游戏实现思路和源码
Apr 14 #Javascript
JS跨域解决方案之使用CORS实现跨域
Apr 14 #Javascript
You might like
基于文本的搜索
2006/10/09 PHP
php中神奇的fastcgi_finish_request
2011/05/02 PHP
浅析echo(),print(),print_r(),return之间的区别
2013/11/27 PHP
php反射应用示例
2014/02/25 PHP
详解PHP中的null合并运算符
2015/12/30 PHP
PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
2019/11/19 PHP
javascript动态修改Li节点值的方法
2015/01/20 Javascript
javascript实现倒计时并弹窗提示特效
2015/06/05 Javascript
JS+CSS实现类似QQ好友及黑名单效果的树型菜单
2015/09/22 Javascript
js数组如何添加json数据及js数组与json的区别
2015/10/27 Javascript
详解JavaScript跨域总结与解决办法
2016/10/31 Javascript
js实现产品缩略图效果
2017/03/10 Javascript
js中less常用的方法小结
2017/08/09 Javascript
详解ES6中的代理模式——Proxy
2018/01/08 Javascript
原生js实现获取form表单数据代码实例
2019/03/27 Javascript
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
2019/05/05 Javascript
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
Python实现的当前时间多加一天、一小时、一分钟操作示例
2018/05/21 Python
python实现求特征选择的信息增益
2018/12/18 Python
详解pandas中MultiIndex和对象实际索引不一致问题
2019/07/23 Python
一文详述 Python 中的 property 语法
2020/09/01 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
美国购买汽车零件网站:Buy Auto Parts
2018/04/02 全球购物
Sneaker Studio捷克:购买运动鞋
2018/07/08 全球购物
Java面试题:请说出如下代码的输出结果
2013/04/22 面试题
党委书记岗位职责
2013/11/24 职场文书
电子商务个人职业生涯规划范文
2014/02/12 职场文书
中青班党性分析材料
2014/02/16 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
会计求职自荐信
2015/03/26 职场文书
辩论会主持词
2015/07/03 职场文书
2015年暑期实践报告范文
2015/07/13 职场文书
2015年高校保卫处工作总结
2015/07/23 职场文书
python实现的人脸识别打卡系统
2021/05/08 Python
详解Python为什么不用设计模式
2021/06/24 Python
win10此电脑打不开怎么办 win10双击此电脑无响应的解决办法
2022/07/23 数码科技