2009-10-12 7 views
48

Je suis curieux de savoir s'il est possible de créer un événement personnalisé dans jQuery qui n'est pas lié à un élément DOM. Je préfère grandement jQuery à YUI mais il y a une chose que j'aime dans YUI, qui est de créer des événements personnalisés et de pouvoir y adhérer plus tard.Événement personnalisé dans jQuery qui n'est pas lié à un élément DOM?

Par exemple, cela crée un événement qui est lié à une variable, et non à un élément DOM:

var myevent = new YAHOO.util.CustomEvent("mycustomevent"); 

Tous les exemples et la documentation que je l'ai lu pour jQuery exigent quelque chose comme:

$('body').bind('mycustomevent', function(){ 
    //do stuff 
}); 
+1

Je suppose que jquery ne comprendra pas du tout les événements 'mycustomevent' et YUI. Cependant, vous pouvez essayer d'utiliser le pointeur: 'bind (myevent,' .. – jantimon

+0

Je pense que, comme Django, il y a quelques bonnes pratiques dans JQuery: dans un premier temps, des plugins.Vous pouvez créer votre événement personnalisé en tant que external class, étant un plug-in pour JQuery, et vous pouvez simplement lier votre événement à votre élément en utilisant n'importe quel sélecteur, comme $ ("# myDiv"). myPlugin ("fait beaucoup de choses") il y a plusieurs façons de faire cela, mais vous devez d'abord reconnaître ce dont vous avez besoin, pouvez-vous élaborer un peu? Je pourrais essayer de vous donner un commentaire plus précis) – 0100110010101

+0

Salut! Ils ont accepté la réponse n'est pas correcte (ou n'est plus correcte * plus *). Pourriez-vous peut-être changer la réponse acceptée à la mienne? – sbichenko

Répondre

43

Vous pouvez déclencher des événements mondiaux personnalisés comme celui-ci dans jQuery:

jQuery.event.trigger('mycustomevent', [arg1, arg2, arg3]); 

Ceux-ci se déclencheront pour n'importe quel élément.

Puisque jQuery est construit autour d'objets DOM, vous devez lier vos événements aux objets DOM. Vous pouvez probablement trouver un moyen de lier des événements sans un élément (vous l'avez fait), mais ce n'est pas une méthodologie supportée.

Comme vous l'avez écrit dans votre réponse, vous pouvez lier votre événement à un objet DOM global si vous ne voulez pas le lier à un élément de page individuelle:

$(document).bind('mycustomevent', function (e, arg1, arg2, arg3) { /* ... */ }); 
+7

ressemble à ce que jQuery supporte maintenant: http://bugs.jquery.com/ticket/7818#comment:26, http://forum.jquery.com/topic/triggering-custom-events-on-js-objects. La solution de contournement 'triggerHandler' mentionnée dans le lien a également été corrigée dans le numéro 7930. – hyperslug

+2

Oui, jQuery supporte actuellement cela (voir ma réponse: http://stackoverflow.com/a/26062543/710356) – sbichenko

6

Pour les futurs lecteurs, son assez simple à faire cela. J'ai fait d'autres recherches après avoir posté ma question. Malheureusement, aucun des autres commentateurs n'avaient raison.

Pour lier un événement personnalisé:

$().bind('mycustomevent', function(){ 
    //code here 
}); 

En outre, vous pouvez construire des données dans l'objet de l'événement qui est plus tard accessible:

$({mydata:'testdata'}).bind('mycustomevent',function(){ 
    //code here 
}); 
+17

Vous devriez savoir qu'avec '$()' vous liez encore à un objet DOM (' $() 'est identique à faire $ (document)'). '$ ({})' fonctionne, mais sachez que cela fonctionne parce que jQuery ne vérifie jamais s'il s'agit d'un objet DOM. Il l'encapsule toujours avec un objet jQuery qui a des méthodes telles que 'append (...)' qui arrêtera votre script s'il est appelé. En outre, le comportement pour l'emballage des objets non-DOM n'est pas défini et peut changer à l'avenir. Je reste donc fidèle à mon point de vue dans ma réponse, et je vous recommande de le lier à '$ (document)' plutôt qu'à un objet JavaScript. – Blixt

3

Vous pouvez déclencher encore arbitraire et réagir aux événements en utilisant jQuery, même si vous ne savez pas à quel élément les attacher. Créez simplement un élément "récepteur" dans votre document, auquel vous pouvez lier tous vos événements personnalisés. Cela vous permet de gérer la logique de gestion des événements en un seul endroit, pour tous vos événements non spécifiques aux éléments.

$(document).ready(function() { 

    $(body).append('<div id="receiver">'); 

    $("#receiver").bind("foo_event", function() { 
    // decide what to do now that foo_event has been triggered. 
    }); 

    $("#some_element").click(function() { 
    $("#receiver").trigger("foo_event"); 
    }); 

}); 
+0

Je pense que c'est une mauvaise idée. Si vous voulez vraiment que certains éléments attirent des événements, pourquoi ne pas utiliser '$ ('body')' ou '$ (document)'? – Blixt

+5

C'est juste une convention qui fonctionne.Je préfère l'utilisation d'un document ou d'un corps, car elle agit en quelque sorte comme une chambre de compensation stérile pour les événements - je sais tout ce qui s'y trouve, et il y a moins de risques que quelque chose de indésirable se produise accidentellement. Pouvez-vous expliquer pourquoi vous pensez que c'est une mauvaise idée? –

5

La liaison aux éléments non dom a été supprimée dans jQuery 1.4.4.

+0

Qu'est-ce que cela signifie? – ppumkin

+0

Peut-être, il signifie des objets JavaScript simples? –

+0

Faites-vous référence à [this] (http://stackoverflow.com/a/26062543/4967497) réponse? – JojOatXGME

3

jQuery Callbacks fournit un moyen simple d'implémenter un système pub-sub indépendant du DOM.

Près du bas de la page liée est un exemple de code qui montre comment faire cela.

1

[EDIT]

est ici une classe ouvrière qui utilise les concepts écrits ci-dessous:

https://github.com/stratboy/image-preloader

Il est juste un préchargement d'image séquentielle. Vous pouvez vous abonner à un tas d'événements. Regarde.

[/ EDIT]

post ancienne:

Voici un autre exemple barebone avec callbacks comme suggéré par Himanshu P.

Je construis une classe et je viens de Mootools, où les choses comme Les classes et les événements personnalisés directement implémentés dans les classes (donc non liés aux éléments DOM) sont absolument naturels. J'ai donc essayé une sorte de solution de contournement et partage ci-dessous.

var step_slider; 

    //sandbox 
    ;(function($) { 

//constructor 
var StepSlider = function(slider_mask_selector,options) { 

    //this.onStep = $.Event('step'); 
    this.options = null; 
    this.onstep = $.Callbacks(); 

    this.init(); 
}//end constructor 

StepSlider.prototype = { 

    init:function(){ 
     this.set_events(); 
    },//end init 

    set_events:function(){ 

     if(this.options){ 
      if(this.options.onstep){ 
       this.subscribe('step',options.onstep); 
      } 
     } 

    },//set_events 

    subscribe:function(event,action){ 
     this['on'+event].add(action); 
    }, 

    fire_onstep:function(){ 
     this.onstep.fire({ data1:'ok' }); 
    } 

}//end prototype/class 

//-------------------- 

$(document).ready(function() { 

    step_slider = new StepSlider('selector'); 

    //for example, say that you have a div#next-button, you can then do this: 
    $('#next-button').click(function(){ 
     step_slider.fire_onstep(); 
    }); 

});//end domready 


})(jQuery); 
+0

ce n'est pas une classe. –

+0

@low_rents: peut-être pas pour ES6, mais tant que vous pouvez instancier des objets (nouveau ClassName), c'est une classe. Ou, c'est un (javascript) moyen de faire quelque chose comme une classe, en gardant à l'esprit que javascript n'avait pas de véritable syntaxe/succes/sucres comme ActionScript 3 et ES6. Probablement l'une des meilleures implémentations js oop avant ES6 était la façon dont coffescript créait des classes js (il suffit de créer un et de voir le code compilé), mais celui ci-dessus est une implémentation plus simple et un bon compromis pour être autonome objets à instancier des temps infinis. – Stratboy

39

Selon a comment by John Resig, événements de liaison à des objets personnalisés via jQuery est pris en charge:

Aucune raison particulière pour laquelle il n'est pas documenté (autre que c'est plutôt non traditionnel pour la plupart des utilisateurs) - mais oui, nous le soutenons et avons des tests unitaires pour cela.

ceci marche:

var a = {foo: 'bar'}; 
$(a).on('baz', function() {console.log('hello')}); 
$(a).triggerHandler('baz'); 
>>> 'hello' 

La plupart des utilisateurs auront besoin triggerHandler(), pas trigger(). Si .trigger("eventName") est utilisé, il recherchera une propriété "eventName" sur l'objet et tentera de l'exécuter après l'exécution des gestionnaires jQuery attachés (Source).

EDIT (28/02/2017):

Après avoir utilisé ce modèle pendant environ 2 ans dans une grande base de code, je peux attester que c'est une mauvaise idée. Ces événements personnalisés conduisent à des flux de données incompréhensibles. Préférer les rappels à la place.

+9

Ceci devrait être la réponse acceptée – MatteoSp

+1

Question idiote: A-t-il une raison pour laquelle il n'est pas documenté? Ne devrait-il pas être utilisé? Pourrait-il être supprimé/modifié dans une version plus récente? Je me demande si je devrais l'utiliser en faveur d'autres bibliothèques sous-pub comme [EvenEmitter] (https://github.com/Olical/EventEmitter). – robsch

Questions connexes