談一談JS消息機(jī)制和事件機(jī)制的理解
消息/事件機(jī)制是幾乎所有開發(fā)語言都有的機(jī)制,并不是deviceone的獨創(chuàng),在某些語言稱之為消息(Event),有些地方稱之為(Message). 其實原理是類似的,只不過有些實現(xiàn)的方式要復(fù)雜一點。我們deviceone統(tǒng)一就叫消息.
消息基礎(chǔ)概念
還有一些初學(xué)者不太熟悉這個機(jī)制,我們先簡單介紹一些基礎(chǔ)概念,如果熟悉的人可以跳過這個部分。
一個/條消息可以理解為是一個數(shù)據(jù)結(jié)構(gòu),包含以下幾個基本部分:
1.消息源:就是消息的來源,發(fā)出這個消息的對象
2.消息名:就是消息的唯一標(biāo)示
3.消息數(shù)據(jù):消息發(fā)出后附帶的數(shù)據(jù),有可能數(shù)據(jù)是空
消息從種類上又可以分為2種:
1.系統(tǒng)消息:由操作系統(tǒng)或deviceone系統(tǒng)發(fā)送出來的消息,消息的名稱是固定的。
2.自定義消息:由開發(fā)者自己定義,自己發(fā)送出來的消息,消息的名字是隨意的,可以任意定義。
舉例說明:
比如用戶點擊一個do_Button按鈕,就會觸發(fā)一個系統(tǒng)消息,包含3個部分:
1.消息源:用戶點中的button對象
2.消息名:touch
3.消息數(shù)據(jù):這個消息沒有附帶數(shù)據(jù)
比如用戶通過do_Button按鈕觸發(fā)一個自定義事件,包含3個部分:
1.消息源: button對象
2.消息名:用戶隨便定義,叫aaa,bbb,ccc都可以
3.消息數(shù)據(jù):附帶的數(shù)據(jù)由觸發(fā)消息的時候設(shè)定
發(fā)布/訂閱模式
發(fā)布/訂閱模式是最常用的設(shè)計模式之一,是消息機(jī)制的核心,其特點就是降低耦合度,讓二個獨立的對象不互相依賴。簡單介紹一下,熟悉的同學(xué)可以跳過。
我們先從現(xiàn)實的一個簡單例子來說明這個問題,參考下圖:

從這個圖我們可以看出
1.消費者和出版社互相不認(rèn)識,消費者不需要了解他想要的雜志是具體哪家出版社出的;出版社也不需要了解具體是哪個人定了他們出版社發(fā)行的書。
2.消費者和出版社必須都認(rèn)識郵局。
3.消費者需要告訴郵局消費者的名字地址以及想要訂閱的雜志名字
4.可以多個消費者訂閱同一本雜志
5.郵局拿到雜志后,會一一通知消費者,通知的時候同時把雜志送到消費者手里。
看完上面現(xiàn)實例子,我們再來看抽象的描述會更清晰一點,看下圖:

和上面的實際例子描述一一對應(yīng):
1.系統(tǒng)/開發(fā)者和函數(shù)對象互相不依賴,系統(tǒng)/開發(fā)者只管觸發(fā)一個消息,并不關(guān)心誰去接受
2.系統(tǒng)/開發(fā)者和函數(shù)對象必須能獲取到消息源對象
3.函數(shù)對象訂閱消息的時候需要標(biāo)示消息的名稱和函數(shù)對象的引用
4.可以多個函數(shù)對象訂閱同一個消息源同一名字的消息
5.消息源觸發(fā)消息會一一通知所有訂閱者,并把data數(shù)據(jù)傳遞到回調(diào)函數(shù)對象
看完抽象的描述,我們最后來看實際的deviceone開發(fā)的例子,還是以do_Button為例子。
1. 當(dāng)用戶點擊一個button,觸摸到的時候,系統(tǒng)會獲取到button這個對象作為消息源,fire一個”touch”消息,任何訂閱了”touch”消息的函數(shù)對象都會接收到這個消息并引起函數(shù)的執(zhí)行。
//獲取button對象
var btn_hello = ui("btn_hello");
//定義函數(shù)對象
function f(){
//當(dāng)btn_hello這個按鈕接收到手指點擊就會執(zhí)行下面的代碼
deviceone.print("f 函數(shù)接收到點擊觸發(fā)消息")
}
function f(){
//當(dāng)btn_hello這個按鈕接收到手指點擊就會執(zhí)行下面的代碼
deviceone.print("f 函數(shù)接收到點擊觸發(fā)消息")
}
//f,f訂閱button的touch消息
btn_hello.on("touch",f);
btn_hello.on("touch",f);
2. 我們可以為button對象定義2個自定義的消息”message1”和”message2”,分別有2個函數(shù)對象訂閱這2個消息。但是最后要觸發(fā)這個消息必須是開發(fā)者通過調(diào)用fire函數(shù)才能觸發(fā),這就是和系統(tǒng)消息的區(qū)別。
//獲取button對象
var btn_hello = ui("btn_hello");
//定義函數(shù)對象
function f(d){
//當(dāng)btn_hello這個按鈕接收到開發(fā)者觸發(fā)的消息message就會執(zhí)行下面的代碼
deviceone.print("f 函數(shù)接收到message消息,消息的數(shù)據(jù)是:"+d)
}
function f(d){
//當(dāng)btn_hello這個按鈕接收到開發(fā)者觸發(fā)的消息message就會執(zhí)行下面的代碼
deviceone.print("f 函數(shù)接收到message消息,消息的數(shù)據(jù)是:"+d)
}
//f,f訂閱button的touch消息
btn_hello.on("message",f);
btn_hello.on("message",f);
//觸發(fā)消息
btn_hello.fire("message","data");
btn_hello.fire("message","data");
看到這里,你肯定會奇怪,為什么我們要在button上自定義對象?這有神馬意義?其實確實沒有意義也沒有必要,這里只是拿button舉例子,在常規(guī)的開發(fā)中,基本不會這么用。
消息的使用
前面講了這么多,現(xiàn)在才是deviceone消息的使用。使用其實很簡單,上面的例子基本說明的了系統(tǒng)事件和自定義事件的使用方法。
有幾個概念再說明一下
1.deviceone的所有對象,包括UI,MM,SM對象都可以是消息源
// SM對象可以是消息源
var page = sm("do_Page");
page.on("loaded",function()){
// 這個是page對象的系統(tǒng)消息,這個消息不需要手動觸發(fā),系統(tǒng)會自動觸發(fā)
}
page.on("message",function(d)){
// 這個是page對象的自定義消息
}
page.fire("message","data");
// MM對象可以是消息源
var http = mm("do_Http");
http.on("result",function()){
// 這個是http對象的系統(tǒng)消息,這個消息不需要手動觸發(fā),接受到http服務(wù)端的反饋后會自動觸發(fā)
}
http.on("message",function(d)){
// 這個是http對象的自定義消息
}
http.fire("message","data");
//UI對象可以是消息源
var alayout = ui("alayout_id");
alayout.on("touch",function()){
// 這個是alayout對象的系統(tǒng)消息,這個消息不需要手動觸發(fā),手機(jī)點擊就會觸發(fā)
}
alayout.on("message",function(d)){
// 這個是alayout對象的自定義消息
}
alayout.fire("message","data");
2.消息源對象有作用域,所以訂閱和觸發(fā)的消息源必須是是一個作用域的同一個對象。這里結(jié)合數(shù)據(jù)分享和數(shù)據(jù)傳遞文檔來理解。
看以下的例子,test1.ui和test2.ui有可能在一個page作用域,也有可能不在一個作業(yè)域,只有在一個作用域fire的消息才能正確送達(dá)回調(diào)函數(shù)。
判斷是否一樣,可以通過打印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觸發(fā)消息
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觸發(fā)消息
var app = sm("do_App");
app.fire("message","data");
3.同樣的函數(shù)對象可以重復(fù)訂閱一個對象源的消息,觸發(fā)消息的時候會使函數(shù)執(zhí)行多次,這是初學(xué)者經(jīng)常犯的錯誤。
var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("執(zhí)行次數(shù)"+(count++));
}
page.on("message",f);
page.on("message",f);
page.fire("message");
看上面的例子,如果執(zhí)行的話,會打印2此,因為訂閱了2次,或許你會說誰會寫這樣的代碼?實際情況肯定沒有這么容易看出來執(zhí)行了重復(fù)的on函數(shù),實際情況經(jīng)常是比如在點擊事件里執(zhí)行on函數(shù),每點擊一下按鈕,就重復(fù)訂閱一次。
4.消息的訂閱一定要在消息的觸發(fā)之前,這是初學(xué)者經(jīng)常犯的錯誤。
var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("執(zhí)行次數(shù)"+(count++));
}
page.fire("message");
page.on("message",f);
看上面的例子,如果執(zhí)行的話,會沒有效果,或許你會說誰會寫這樣的代碼?實際情況肯定沒有這么容易看出來順序反了,實際情況經(jīng)常是比如on函數(shù)執(zhí)行在某一個函數(shù)的回調(diào)函數(shù)里,你無法確定回調(diào)函數(shù)啥時候執(zhí)行,是否是在fire之前執(zhí)行。一般碰到這種情況可以加幾個deviceone.print打印一下看看是on先執(zhí)行還是fire先執(zhí)行。
5.有訂閱就有取消訂閱,取消訂閱是off函數(shù),之所以很少用,是因為closePage的時候會自動把當(dāng)前page作用域訂閱的消息全部釋放。
但是如果消息訂閱在app作用域,就要注意,可能需要手動去取消訂閱。否則就會出現(xiàn)觸發(fā)消息的時候會使函數(shù)執(zhí)行多次的問題。
var page = sm("do_Page");
var count = ;
function f(){
deviceone.print("執(zhí)行次數(shù)"+(count++));
}
page.on("message",f);
page.fire("message");
.page.off("message");
page.fire("message");
看上面的例子,打印只會執(zhí)行一次,因為fire一次后就取消訂閱了。
相關(guān)文章
JavaScript中各種時間轉(zhuǎn)換問題詳解(YYYY-MM-DD、時間戳、中國標(biāo)準(zhǔn)時間)
在某些場景下,需要將時間轉(zhuǎn)換為字符串進(jìn)行展示或傳遞,下面這篇文章主要給大家介紹了關(guān)于JavaScript中各種時間轉(zhuǎn)換問題(YYYY-MM-DD、時間戳、中國標(biāo)準(zhǔn)時間)的相關(guān)資料,需要的朋友可以參考下2024-02-02
javascript實現(xiàn)數(shù)組內(nèi)值索引隨機(jī)化及創(chuàng)建隨機(jī)數(shù)組的方法
這篇文章主要介紹了javascript實現(xiàn)數(shù)組內(nèi)值索引隨機(jī)化及創(chuàng)建隨機(jī)數(shù)組的方法,涉及javascript數(shù)組索引及隨機(jī)數(shù)的相關(guān)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08
javascript:json數(shù)據(jù)的頁面綁定示例代碼
本篇文章主要是對javascript:json數(shù)據(jù)的頁面綁定示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01
利用js實現(xiàn)前臺動態(tài)添加文本框,后臺獲取文本框內(nèi)容(示例代碼)
這篇文章主要是對利用js實現(xiàn)前臺動態(tài)添加文本框,后臺獲取文本框內(nèi)容的示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11
javascript中的return和閉包函數(shù)淺析
這篇文章主要介紹了javascript中的return和閉包函數(shù)淺析,至少可以讓你搞懂那么多()是什么意思,需要的朋友可以參考下2014-06-06
JS實現(xiàn)定時自動關(guān)閉DIV層提示框的方法
這篇文章主要介紹了JS實現(xiàn)定時自動關(guān)閉DIV層提示框的方法,可實現(xiàn)加載時載入js代碼控制div層提示框自動關(guān)閉的效果,非常簡單實用,需要的朋友可以參考下2015-05-05
Bootstrap popover 實現(xiàn)鼠標(biāo)移入移除顯示隱藏功能方法
下面小編就為大家分享一篇Bootstrap popover 實現(xiàn)鼠標(biāo)移入移除顯示隱藏功能方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01

