ホームページ >ウェブフロントエンド >jsチュートリアル >JSメッセージの仕組みとイベントの仕組みの理解_JavaScriptスキルについて話しましょう

JSメッセージの仕組みとイベントの仕組みの理解_JavaScriptスキルについて話しましょう

WBOY
WBOYオリジナル
2016-05-16 15:05:381599ブラウズ

メッセージ/イベント メカニズムは、ほとんどすべての開発言語に見られるメカニズムであり、deviceone に固有のものではなく、一部の言語ではメッセージ (イベント) と呼ばれます。原理は似ていますが、一部の実装方法が少し複雑です。私たちのデバイスの統一名はメッセージと呼ばれます。

メッセージの基本概念

このメカニズムに慣れていない初心者もいます。慣れている場合は、この部分を飛ばしてください。
メッセージは、次の基本部分を含むデータ構造として理解できます:

1. メッセージソース: メッセージのソースおよびメッセージを送信するオブジェクトです

2. メッセージ名: メッセージの一意の識別子です。

3. メッセージデータ: メッセージの送信後に添付されるデータ。データは空の場合があります

メッセージは 2 つのタイプに分類できます:

1. システムメッセージ: オペレーティングシステムまたはデバイスシステムによって送信されるメッセージの名前は固定されています。

2. カスタムメッセージ: メッセージは開発者自身が定義し、自分で送信します。メッセージの名前は任意であり、任意に定義できます。

例:

たとえば、ユーザーが do_Button ボタンをクリックすると、次の 3 つの部分を含むシステム メッセージがトリガーされます。

1. メッセージソース: ユーザークリック時のボタンオブジェクト

2. メッセージ名:
をタッチします。

3. メッセージ データ: このメッセージにはデータが付属しません

たとえば、ユーザーは do_Button ボタンを通じてカスタム イベントをトリガーします。これには 3 つの部分が含まれます。

1.メッセージソース: ボタンオブジェクト

2. メッセージ名: ユーザーは必要に応じて定義できます。aaa、bbb、ccc と呼ぶことができます

3. メッセージデータ: メッセージがトリガーされたときに添付データが設定されます

パブリッシュ/サブスクライブモード

パブリッシュ/サブスクライブ パターンは、最も一般的に使用される設計パターンの 1 つであり、その特徴は、2 つの独立したオブジェクトが互いに依存しないように結合を減らすことです。簡単な紹介なので、慣れている学生は読み飛ばしてかまいません。

まず、現実の簡単な例でこの問題を説明しましょう。下の図を参照してください。


この写真からわかります

1. 消費者と出版社はお互いを知りません。消費者は、自分が欲しい雑誌をどの出版社が発行しているかを知る必要はありません。出版社は、自分が欲しい雑誌を具体的に誰が注文したかを知る必要はありません。

2. 消費者と出版社の両方が郵便局を知っている必要があります。

3. 消費者は郵便局に消費者の名前と住所、購読したい雑誌の名前を伝える必要があります

4. 複数の消費者が同じ雑誌を購読できます

5.郵便局は雑誌を受け取った後、消費者に順次通知し、同時に雑誌を消費者に配達します。

上記の実例を読んだ後、より明確にするために抽象的な説明を見てみましょう:

は、上記の実際の例の説明に対応します:

1. システム/開発者と関数オブジェクトは相互に依存しません。システム/開発者はメッセージをトリガーするだけであり、誰がメッセージを受信するかは気にしません。

2. システム/開発者オブジェクトと関数オブジェクトはメッセージ ソース オブジェクトを取得できる必要があります


3. 関数オブジェクトがメッセージをサブスクライブする場合、メッセージの名前と関数オブジェクトへの参照を示す必要があります


4. 複数の関数オブジェクトが同じメッセージ ソースと同じ名前をサブスクライブできます


5. メッセージ ソースがメッセージをトリガーすると、すべてのサブスクライバーに 1 つずつ通知し、データをコールバック関数オブジェクトに渡します


抽象的な説明を読んだ後、最後に do_Button を例として実際の deviceone 開発例を見てみましょう。


1. ユーザーがボタンをクリックしてタッチすると、システムはボタン オブジェクトをメッセージ ソースとして取得し、「タッチ」メッセージをサブスクライブする関数オブジェクトを起動します。このメッセージによって関数が実行されます。

//获取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. ボタン オブジェクトに対して 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一次后就取消订阅了。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。