訊息/事件機制幾乎是所有開發語言都有的機制,並不是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一次后就取消订阅了。

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

本文將引導您使用jQuery庫創建一個簡單的圖片輪播。我們將使用bxSlider庫,它基於jQuery構建,並提供許多配置選項來設置輪播。 如今,圖片輪播已成為網站必備功能——一圖胜千言! 決定使用圖片輪播後,下一個問題是如何創建它。首先,您需要收集高質量、高分辨率的圖片。 接下來,您需要使用HTML和一些JavaScript代碼來創建圖片輪播。網絡上有很多庫可以幫助您以不同的方式創建輪播。我們將使用開源的bxSlider庫。 bxSlider庫支持響應式設計,因此使用此庫構建的輪播可以適應任何

將矩陣電影特效帶入你的網頁!這是一個基於著名電影《黑客帝國》的酷炫jQuery插件。該插件模擬了電影中經典的綠色字符特效,只需選擇一張圖片,插件就會將其轉換為充滿數字字符的矩陣風格畫面。快來試試吧,非常有趣! 工作原理 插件將圖片加載到畫布上,讀取像素和顏色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地讀取圖片的矩形區域,並利用jQuery計算每個區域的平均顏色。然後,使用

本文說明瞭如何使用源地圖通過將其映射回原始代碼來調試JAVASCRIPT。它討論了啟用源地圖,設置斷點以及使用Chrome DevTools和WebPack之類的工具。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver CS6
視覺化網頁開發工具

Dreamweaver Mac版
視覺化網頁開發工具

記事本++7.3.1
好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。