消息/事件机制是几乎所有开发语言都有的机制,它不是deviceone的最初创建。它在某些语言中被称为事件,在某些地方被称为信息。其实原理差不多,只是有些实现方法有点复杂。我们的设备一被称为信息。
传达基本概念。
有一些初学者不熟悉这个机制。先简单介绍一些基本概念,熟悉的可以跳过这一部分。消息可以理解为数据结构,它包括以下基本部分:
1.消息来源:它是消息的来源,也是发送消息的对象。
2.消息名称:这是消息的唯一标记。
3.报文数据:报文发送后附加的数据,可能为空。
消息可以分为两类:
1.系统消息:由操作系统或deviceone系统发送的消息,消息的名称是固定的。
2.用户定义的消息:由开发人员自己定义。开发人员发送的消息的名称是任意的,可以随意定义。
举个例子:
例如,当用户单击do_Button时,将会触发一条系统消息,该消息包括三个部分:
1.消息来源:用户点中的按钮对象。
2.消息名称:触摸。
3.消息数据:此消息没有附加数据。
例如,用户通过do_Button按钮触发自定义事件,该按钮包括三个部分:
1.消息源:按钮对象。
2.消息名:用户可以随便定义,可以叫aaa、bbb、ccc。
3.消息数据:当消息被触发时,附加数据被设置。
发布/订阅模式
发布/订阅模式是最常用的设计模式之一,是消息机制的核心。其特点是降低耦合度,使两个独立的对象相互独立。简单介绍一下,熟悉的同学可以跳过。
我们先从一个简单的现实例子来说明这个问题,参考下图:
从这张照片我们可以看出。
1.消费者和出版商互不了解,消费者也不需要知道哪个出版商是自己想要的杂志。出版社也不需要知道是谁订了他们出版社出版的书。
2.消费者和出版商都必须知道邮局。
3.消费者需要告诉邮局消费者的姓名和地址以及他想订阅的杂志的名称。
4.多个消费者可以订阅同一份杂志。
5.邮局拿到杂志后,会逐一通知消费者,同时将杂志寄给消费者。
看完上面的实例,我们会看到抽象的描述会更加清晰,见下图:
与上述实际示例描述一一对应:
1.系统/开发人员和函数对象是相互独立的,系统/开发人员只触发一条消息,并不关心是谁收到的。
2.系统/开发人员和功能对象必须能够获得消息源对象。
3.当函数对象订阅消息时,需要标记消息的名称和函数对象的引用。
4.多个函数对象可以订阅来自同一消息源的同名消息。
5.消息源触发消息会逐一通知所有订阅者,并将数据数据传递给回调函数对象。
看完抽象描述,我们最后再来看deviceone开发的实际例子,或者以do_Button为例。
1.当用户点击一个按钮并触摸它时,系统将获得对象按钮作为消息源,fire就是一个“touch”消息。订阅“touch”消息的任何函数对象都会收到该消息,并导致函数执行。
//获取按钮对象var BTN _ hello=ui(' BTN _ hello ');//定义函数对象function f(){//当btn_hello按钮收到手指点击时,将执行如下代码deviceone.print('f function收到点击触发消息')}function f(){//当按钮btn_hello收到手指点击时,将执行如下代码deviceone.print('f function收到点击触发消息')}//f,f订阅按钮的触摸消息btn_hello.on('touch,f);btn_hello.on('touch ',f);2.我们可以为按钮对象定义两个用户定义的消息“message1”和“message2”,两个函数对象分别订阅这两个消息。但最终消息必须由开发人员通过调用fire函数来触发,这与系统消息不同。
//获取按钮对象var BTN _ hello=ui(' BTN _ hello ');//定义函数对象函数f(d){//当btn_hello接收到开发者触发的消息消息时,会执行下面的代码deviceone.print('f函数接收到消息消息,消息数据为:' d)}函数f(d){//当btn_hello button接收到开发者触发的消息时,会执行下面的代码deviceone.print('f函数接收到消息,消息数据为:' d)}//f,f订阅button的触控消息btn_hello。btn_hello.on('message ',f);//触发消息btn_hello.fire('message ',' data ');btn_hello.fire('message ',' data ');看到这一点,你一定想知道为什么我们要自定义按钮上的对象。这有什么意义?其实是没有意义,没有必要的。这里只是按钮的一个例子,在正常开发中基本不用。
信息的使用。
说了这么多,现在是使用deviceone消息。其实用起来很简单。上面的例子基本上说明了系统事件和自定义事件的使用。
有几个概念再解释一下。
1.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 ',函数(d)){//这是http对象}http.fire('message ',' data ')的自定义消息。//UI对象可以是消息源var alayout=UI(' alayout _ id ');Alayout.on ('touch ',function()){//这是Alayout对象的系统消息。此消息不需要手动触发。手机点击时,} Alayout.on ('message ',函数(d)){//这是Alayout对象}alayout.fire('message ',' data ')的自定义消息。2.消息源对象有作用域,因此订阅和触发的消息源必须是具有相同作用域的同一对象。这可以通过结合数据共享和数据传输文档来理解。
看下面的例子,test1.ui和test2.ui可能在页面范围内,也可能不在作业范围内,只有作用域fire中的消息才能正确传递给回调函数。
要判断它们是否相同,可以打印地址页。
//订阅test.ui.js中的消息var Page=sm(' do _ Page ');device one . print(page . GetAddress());page.on('message ',function(d)){ device one . print(d);}//触发test.ui.js中的消息var Page=sm(' do _ Page ');device one . print(page . GetAddress());page.fire('message ',' data ');如果它们不在同一页面范围内,您可以将消息订阅可由两个页面共享的应用程序范围上方的代码更改为:
//订阅test.ui.js中的消息var App=sm(' do _ App ');app.on('message ',函数(d)){ device one . print(d);}//触发test.ui.js中的消息var App=sm(' do _ App ');app.fire('message ',' data ');3.同一个函数对象可以重复订阅一个对象源的消息,当消息被触发时,函数会被多次执行,这是初学者常犯的错误。
var Page=sm(' do _ Page ');var count=;函数f(){deviceone.print('执行次数'(计数));}page.on('message ',f);page.on('message ',f);page.fire(“消息”);看上面的例子,如果执行,会打印2份,因为已经订阅了2次,也许你会说这样的代码谁来写?实际情况当然不是那么容易看到重复on函数被执行。实际情况往往是在点击事件中执行on函数,每次点击按钮,订阅都会重复一次。
4.消息的订阅必须在消息触发之前,这是初学者常犯的错误。
var Page=sm(' do _ Page ');var count=;函数f(){deviceone.print('执行次数'(计数));} page . fire(' message ');page.on('message ',f);看上面的例子,如果执行,就没有效果了。也许你会说谁会写这样的代码?实际情况当然不是那么容易看到顺序颠倒的。实际情况往往是,比如在某个函数的回调函数中执行on函数,你无法确定回调函数什么时候执行,或者是否会在激发前执行。一般来说,在这种情况下,可以添加几个deviceone.print进行打印,看看是先执行on还是先执行fire。
5.如果有订阅,就会有退订。取消订阅是一个关闭功能,很少使用,因为当您关闭页面时,当前页面范围订阅的所有消息都将自动释放。
但是,如果消息订阅在应用程序范围内,则应注意可能需要手动取消订阅。否则就会出现消息被触发时函数会被多次执行的问题。
var Page=sm(' do _ Page ');var count=;函数f(){deviceone.print('执行次数'(计数));}page.on('message ',f);page.fire(“消息”); page . off(' message ');page.fire(“消息”);看上面的例子,打印只会执行一次,因为火会取消订阅一次。