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

 更新时间:2016年4月17日 10:00  点击:1363

消息/事件机制是几乎所有开发语言都有的机制,并不是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.消息数据:附带的数据由触发消息的时候设定

发布/订阅模式

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

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


从这个图我们可以看出

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

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

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

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

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

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

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

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一次后就取消订阅了。

[!--infotagslink--]

相关文章

  • JavaScript判断浏览器及其版本信息

    本篇文章主要分享了通过window.navigator来判断浏览器及其版本信息的实例代码。具有一定的参考价值,下面跟着小编一起来看下吧...2017-01-23
  • js实现浏览器打印功能的示例代码

    这篇文章主要介绍了js如何实现浏览器打印功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-15
  • Nest.js参数校验和自定义返回数据格式详解

    这篇文章主要给大家介绍了关于Nest.js参数校验和自定义返回数据格式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-28
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • 详解前端安全之JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
  • js实现调用网络摄像头及常见错误处理

    这篇文章主要介绍了js实现调用网络摄像头及常见错误处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-07
  • JS实现随机生成验证码

    这篇文章主要为大家详细介绍了JS实现随机生成验证码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-06
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • js组件SlotMachine实现图片切换效果制作抽奖系统

    这篇文章主要介绍了js组件SlotMachine实现图片切换效果制作抽奖系统的相关资料,需要的朋友可以参考下...2016-04-19
  • vue.js 表格分页ajax 异步加载数据

    Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统.这篇文章主要介绍了vue.js 表格分页ajax 异步加载数据的相关资料,需要的朋友可以参考下...2016-10-20
  • js实现列表按字母排序

    这篇文章主要为大家详细介绍了js实现列表按字母排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-11
  • 基于JavaScript实现文字超出部分隐藏

    这篇文章主要介绍了基于JavaScript实现文字超出部分隐藏 的相关资料,需要的朋友可以参考下...2016-03-01
  • js+css实现回到顶部按钮(back to top)

    这篇文章主要为大家详细介绍了js+css实现回到顶部按钮back to top回到顶部按钮,感兴趣的小伙伴们可以参考一下...2016-03-03
  • NodeJS实现阿里大鱼短信通知发送

    本文给大家介绍的是nodejs实现使用阿里大鱼短信API发送消息的方法和代码,有需要的小伙伴可以参考下。...2016-01-20
  • JS实现响应鼠标点击动画渐变弹出层效果代码

    这篇文章主要介绍了JS实现响应鼠标点击动画渐变弹出层效果代码,具有非常自然流畅的动画过度效果,涉及JavaScript针对鼠标事件的响应及页面元素样式的动态操作相关技巧,需要的朋友可以参考下...2016-03-28
  • 浅析AngularJS Filter用法

    系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter。如果对smarty比较熟悉的话,学习angularjs会比较容易一点,这篇文章给大家介绍angularjs filter用法详解,感兴趣的朋友一起学习吧...2015-12-29
  • node.JS md5加密中文与php结果不一致怎么办

    这次文章要给大家介绍的是node.JS md5加密中文与php结果不一致怎么办,不知道具体解决办法的下面跟小编一起来看看。 因项目需要,需要Node.js与PHP做接口调用,发现nod...2017-07-06
  • JavaScript仿支付宝密码输入框

    那么今天我就用JavaScript代码来实现这个效果吧,那么首先介绍一下整个的思路,首先我们先将确定输入密码的位数,我的需求是5位,那么就用一个div标签包住5个input标签...2016-01-02
  • 一个关于JS正则匹配的踩坑记录

    这篇文章主要给大家介绍了一个关于JS正则匹配的踩坑记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-13
  • 基于JavaScript实现表单密码的隐藏和显示出来

    为了网站的安全性,很多朋友都把密码设的比较复杂,但是如何密码不能明显示,不知道输的是对是错,为了安全起见可以把密码显示的,那么基于js代码如何实现的呢?下面通过本文给大家介绍JavaScript实现表单密码的隐藏和显示,需要的朋友参考下...2016-03-03