2015-03-02 11 views
8
function bubble(content, triggerElm){ 
    this.element = $('<div class="bubble" />').html(content); 
    this.element.css(.....) // here is positioned based on triggerElm 
} 

bubble.prototype.show = function(){ 
    $(document).on('click', this._click.bind(this)); 
    this.element.css(....) 
}; 

bubble.prototype.hide = function(){ 
    $(document).off('click', this._click.bind(this)); 
    this.element.css(....) 
}; 

bubble.prototype._click = function(event){ 
    console.log('click', this); 

    if(this.element.is(event.target) || (this.element.has(event.target).length > 0)) 
    return true; 

    this.hide(); 
}; 

var b = new bubble(); 
b.show(); 
b.hide(); 

Continuo a vedere clic nella console, quindi il clic non si slega. Ma se rimuovo la chiamata bind() il clic non è bloccato. Qualcuno sa perché? Ho bisogno di un modo per essere in grado di cambiare "questo" dentro la mia funzione di test, è per questo che sto usando bind()jQuery off() non si scioglie gli eventi quando si utilizza bind

risposta

4

Il problema è che this._click.bind() crea una nuova funzione ogni volta che viene chiamato. Per staccare un gestore di eventi specifico, è necessario passare la funzione originale che è stata utilizzata per creare il gestore di eventi e che non sta succedendo qui, quindi il gestore non viene rimosso.

Se nella tua app ci saranno solo alcuni bubble, potresti seguire la rotta di Douglas Crockford e semplicemente non usare this. Che rimuoverà un sacco di confusione su ciò che this si riferisce e garantire che ogni bubble mantiene un riferimento alla sua propria funzione click che può essere utilizzato per rimuovere l'evento come necessario:

function bubble(content, tiggerElm) { 
    var element = $('<div class="bubble" />').html(content); 
    element.css(.....); // here is positioned based on triggerElm 

    function click(event) { 
     console.log('click', element); 
     if (element.is(event.target) || 
      element.has(event.target).length > 0) { 
      return true; 
     } 
     hide(); 
    } 

    function show() { 
     $(document).on('click', click); 
     element.css(....); 
    } 

    function hide() { 
     $(document).off('click', click); 
     element.css(....); 
    } 

    return { 
     show: show, 
     hide: hide 
    }; 
} 

var b1 = bubble(..., ...); 
b1.show(); 

var b2 = bubble(..., ...); 
b2.show(); 

vedere come questo si libera dall'uso di congegni come il .bind() e i metodi con prefisso sottolineato.

+0

ma non riesco ad accedere a "questo" istanza all'interno del clic – Elfy

+0

@Elfy Sì, è vero. A cosa ti serve? – JLRishe

+0

Bene, ho bisogno di essere in grado di dire se il clic era al di fuori dell'elemento bolla, e questo è parte dell'istanza. Fondamentalmente all'interno della funzione click Im controllo se e.target è this.element o al suo interno – Elfy

5

Una possibilità potrebbe essere quella di namespace the event:

$(document).on('click.name', test.bind(this)); 
$(document).off('click.name'); 

Example Here

+0

Josh Crozier, significherebbe che ogni evento legato al namespace viene cancellato. non sono sicuro se questo è ciò che vuole. –

+1

@NetaMeta Quindi dargli un nome univoco e non dovrebbe essere un problema. –

+1

@ Josh Crozier - quindi perché utilizzare i contenitori o perché preoccuparsi di mantenere globale chiaro - basta nominare i nomi univoci variabile ... –

3

prega leggere https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

legano crea una nuova funzione quindi facendo $(document).on('click', test.bind(this)); è come $(document).on('click', function(){}); e ogni volta che lo si esegue si richiama una nuova funzione anonima quindi non avete un riferimento a un bind.

Se volete fare qualcosa di simile:

var test = function(){ 
    console.log('click'); 
}; 

var newFunct = test.bind(this); 
$(document).on('click', newFunct); 
$(document).off('click', newFunct); 

Dovrebbe funzionare bene

es: http://jsfiddle.net/508dr0hv/

Inoltre - utilizzando bind non è raccomandato, la sua lenta e non è supportato in alcuni browser.

+0

grazie. ma cosa succede se la mia funzione di test fa parte di un oggetto, come legarlo allora? Intendo dove lo faccio :) – Elfy

+1

Elfy aggiungi quel caso alla tua domanda per dimostrare cosa intendi. –

+0

ok ho aggiunto il codice che è più vicino alla mia situazione reale – Elfy

4

prova ad usare il proxy di jQuery per ottenere un riferimento univoco della tua funzione.

In questo modo, quando si chiama $ .proxy (test, questo), verrà verificato se questa funzione è già stata referenziata in precedenza. Se sì, il proxy ti restituirà tale riferimento, altrimenti ne creerà uno e te lo restituirà. In questo modo, puoi sempre ottenere la tua funzione originale, piuttosto che crearla più e più volte (come usare bind).

Pertanto, quando si chiama fuori() e si passa il riferimento della funzione di test, off() rimuoverà la funzione dall'evento click.

E inoltre, la funzione di test deve essere dichiarata prima di utilizzarla.

var test = function(){ 
     console.log('click'); 
};  

$(document).on('click', $.proxy(test, this)); 
$(document).off('click', $.proxy(test, this)); 

http://jsfiddle.net/aw50yj7f/

+0

grazie, sembra funzionare :) – Elfy

+0

Ti rendi conto che il proxy è lento come l'inferno giusto? –

+0

ma si chiama solo in mostra/nascondi – Elfy

Problemi correlati