1

私が書いたクラスから必死にイベントを発生させようとしています。YUI ウィジェット内でこのクラスを使用し、発生したイベントに YUI ウィジェットが応答するようにします。イベントのバブリングがどのように機能しているかはわかっているので、このコードは問題なく機能しています。

    YUI().use('event-custom', 'node', function (Y) {

function Publisher(bubbleTo) {
        this.addTarget(bubbleTo);
        this.publish("testEvent", {
            emitFacade: true
        });
        this.fire("testEvent");
}

function BubbleTarget() {

    this.on("testEvent", function (e) {Y.log("Bubbling in Test.js succeed!")});
    var newPublisher = new Publisher(this);
}
// To fire events or be a bubble target, augment a class with EventTarget
Y.augment(Publisher, Y.EventTarget);
Y.augment(BubbleTarget, Y.EventTarget);

var bubbleTarget = new BubbleTarget();});

ただし、この概念をウィジェットに適用しようとすると、非常に失敗します。

YUI.add("SlideShow", function(Y) {

function SlideShow(config) {
    SlideShow.superclass.constructor.apply(this, arguments);
}

SlideShow.NAME = "SlideShow";

Y.extend(SlideShow, Y.Widget, {
    initializer: function() {   
        Y.log("Widget loaded!");
        this.on("testEvent", function () {
                Y.log("This should, but won't appear despite how hard I try!");
          });
    },

    renderUI: function(){
        var testSlide = new Slide("text", this);
    }
});

Y.SlideShow = SlideShow;

function Slide(sendTo)
{
this.addTarget(sendTo);
    this.publish("testEvent", {
        defaultFn: function(){Y.log('Event published.')},
        emitFacade: true
    });
    this.fire("testEvent");
}

Y.augment(Slide,Y.EventTarget, true, null, {emitFacade: true});
}, "0.0.1", {requires:["widget","event-custom","node","anim"]});

Chromium のログ出力は次のとおりです。

  • Test.js でのバブリングが成功しました!
  • ウィジェットがロードされました!
  • イベント公開。

Widgets に不可欠な何かが本当に欠けているようです。この問題をよりよく理解するために、私を助けてください。

4

3 に答える 3

1

答えはミッチの投稿にあると思います。バブル ターゲット サブスクリプションでイベントのプレフィックスを付ける必要があります。そうではなく:

this.on("testEvent", function () {
    Y.log("This should, but won't appear despite how hard I try!");
});

試す:

this.on("*:testEvent", function () {
    Y.log("This should, but won't appear despite how hard I try!");
});

または、Slide クラスに .NAME を設定します (とにかくこれを行う必要があります)。

Slide.NAME = "Slide";

そして、プレフィックスはその値を使用します:

this.on("Slide:testEvent", function () {
    Y.log("This should, but won't appear despite how hard I try!");
});

Y.Base.create を使用すると、大量のボイラープレートが切り取られます。

于 2012-08-27T13:18:23.627 に答える
0

面白い質問です!

それで、私はもっと深く行き、問題を切り離そうとしました。

まず、@ Mitchの例をテストしました-期待どおりに機能します!証明: http: //jsfiddle.net/pqr7/hQBHH/3/

しかし、Slideがプレーンオブジェクト(Y.Baseから拡張されていない)の場合はどうなりますか?@ brian-j-millerの例をテストしましたが、機能しません。証明: http: //jsfiddle.net/pqr7/hQBHH/4/

次に、Firebugを実行し、YUIソースに段階的に飛び込みます。そして今、私はそれがどのように機能するかを詳細に知っています!

プレーンオブジェクトSlideの例を見てみましょうhttp://jsfiddle.net/pqr7/hQBHH/4/プレーンオブジェクトSlideで 行うthis.fire("testEvent");と、YUIは内部でチェーン内の多くの関数を呼び出し、typestring = "testEvent"(Iソースコードでは常に「type」という名前の変数に保存されるため、「type」と呼びます。予想通り、イベントがバブルし、ターゲット(SlideShowのインスタンス)が豊富であることがわかりました。次に、SlideShowにtype== "testEvent"?のイベントのサブスクライバーがいるかどうかを確認します。回答:いいえ!

this.on('testEvent', ...)実際に文字列として保存されているスライドショー内でサブスクリプションを作成する場合type=="SlideShow:testEvent"

this.on('*:testEvent', ...)実際に文字列として保存されているスライドショー内でサブスクリプションを作成する場合type=="*:testEvent"

this.on('Slide:testEvent', ...)実際に文字列として保存されているスライドショー内でサブスクリプションを作成する場合type=="Slide:testEvent"

しかし、バブルされているのは単純ですtype=="testEvent"なので、SlideShowインスタンス内にサブスクライバーはありません。

次に、YUIは。を使用してより複雑なルールをチェックし*:testEventます。残念ながら、単純な文字列testEventはパターンと一致しません*:testEvent 。元のコードは次のとおりですhttp://yuilibrary.com/yui/docs/api/files/event-custom_js_event-target.js.html#693

if (type.indexOf(PREFIX_DELIMITER) > -1) { /* make a magic to execute a subscriber */ }

typeこれがバブル文字列testEventで、PREFIX_DELIMITER(コロン)は含まれていません

そして、これはY.BaseからSlideを拡張するときの違いです-ファイアリングイベントは単純ではありませんtestEventSlide:testEvent、パターンを一致させます*:testEvent(http://jsfiddle.net/pqr7/hQBHH/3/)

于 2012-08-29T09:18:05.107 に答える
0

プレーンな JS オブジェクトと Y.Widget が相互作用しなければならないときに、2 つのプレーンな JS オブジェクトで動作しているにもかかわらず、なぜ失敗するのかはわかりません。

ただし、Y.Baseを拡張すると問題が解決し、Y.Base の機能を最大限に活用できます。

function Slide(config)
{
    Slide.superclass.constructor.apply(this, config);
}

Slide.NAME = "slide";

Y.extend(Slide, Y.Base, {

    initializer : function() {
               this.publish("testEvent", {
                  emitFacade: true//you do not need to specify this, 
                                  //it will be set implicitly to true
                                  //when using Y.Base
                });
            },
    test : function(arg) {
        this.addTarget(arg);
        this.fire("testEvent");
    }
});

ここで重要なのは NAME 属性です。これは、ウィジェットがリッスンするためのプレフィックスになります。

Y.extend(SlideShow, Y.Widget, {
    initializer: function() {   
       Y.log("Widget loaded!");
       this.on("slide:testEvent", function () {
            Y.log("This will work!");
        });

       this.on("*:testEvent", function () {
            Y.log("This will work, too no matter what's the Event's prefix!");
        });

       this.on("Slide:testEvent", function () {
              Y.log("This won't work, since the prefix doesn't match the NAME-Attribute!");
        });
    },
    //rendering etc.
});

renderUI では、以下を呼び出します。

renderUI: function(){
    var testSlide = new Slide();
    testSlide.on('testEvent', function(e) {
       Y.log('You can listen for testEvent without a prefix on a Slide-object.');
    });
    testSlide.test(this);//adds this Widget as the target for the testSlide. 
}
于 2012-08-26T22:22:40.030 に答える