Привязать событие относительно класса, который его создал?

#javascript #jquery #class #events #bind

#javascript #jquery ( jquery ) #класс #Мероприятия #привязка

Вопрос:

Допустим, у меня есть класс, составленный следующим образом:

 function slider() {

    this.init = function(options, title, content) {
        var self = this;
        $('body').append('<button type="button">'   title   '</button>')
    },    
    this.create = function(title, content, options) {
        var self = this;
        self.init(options, title, content);
    },
    this.closeSlider = function(elem) {
        var self = this;
        self.assignPositions();    
    },

    this.assignPositions = function() {
        alert('assign positions called from button?');
    }
}
 

Чтобы создать «слайдер», я использую это:

var slider = new slider();

Затем я вызываю функцию create:

slider.create('title', 'content');

Мой вопрос в том, как я могу привязать функцию closeSlider к кнопке, но она связана только с экземпляром, который ее создал? Если это имеет смысл?

В принципе, у меня будет много кнопок с функцией ‘closeSlider’, и я не хочу, чтобы все они срабатывали одновременно, я только хочу, чтобы они были связаны с экземпляром, который его создал.

Это также ОЧЕНЬ урезанная версия моего класса, просто пытаюсь разобраться с этой маленькой проблемой 🙂

Приветствия

Комментарии:

1. В повторном выполнении нет смысла var self = this; self.assignPositions(); this.assignPositions() .

2. рассмотрите возможность использования $.text(title) вместо того, чтобы рисковать обработкой заголовка как html

3. Разве это не сэкономило бы память @FelixKling?

4. Как именно это должно экономить память? self this в этом случае это просто псевдоним.

5. Мне только что сказали, что это так, поскольку сохранение в качестве псевдонима является более быстрым поиском, это может быть неправильно, но это именно то, чему меня научили @FelixKling

Ответ №1:

Используйте привязку к функции обратного вызова при настройке обратного вызова события

 this.init = function(options, title, content) {
    var btn = $('<button type="button">'   title   '</button>');
    btn.click(this.closeSlider.bind(this));
    $('body').append(btn)
},  
 

Это сделает так, чтобы при closeSlider вызове функции она сохраняла контекст slider экземпляра, который ее создал. Но примечание this больше не будет контекстом элемента html, который вызвал событие. Итак, вам нужно будет получить цель из event.target

Может быть другой способ сделать это без потери контекста html-элемента, который мне нужно будет просмотреть и отредактировать заново.

Редактировать

Использование event.target

 this.init = function(options, title, content) {
    var btn = $('<button type="button">'   title   '</button>');
    btn.click(this.closeSlider.bind(this));
    $('body').append(btn)
},  
this.closeSlider:function(event){
   //`this` will refer to slider instance
   //and event.target will be the button dom object
   var element = event.target;
});
 

Передача объекта button в качестве аргумента в bind

 this.init = function(options, title, content) {
    var btn = $('<button type="button">'   title   '</button>');
    btn.click(this.closeSlider.bind(this,btn));
    $('body').append(btn)
},  
this.closeSlider:function(btn,event){
   //`this` will refer to slider instance
   //btn will refer to the jQuery wrapped button dom object
   //event.target will still refer to the button dom object
});
 

Комментарии:

1. Используя jquery, является ли это тем же эквивалентом? $(«<кнопка />»).attr({‘onclick’:this.closeSlider,’type’: ‘кнопка’});

2.@ShannonHochkins: btn.click(...); есть ли jQuery: api.jquery.com/click . Я думаю, вам следует прочитать learn.jquery.com/events/event-basics

3. Хотя я, возможно, использовал ответ @jSangs, я принял вас, потому что это практически одно и то же, и вы были первыми!

4. Если бы я использовал это btn.click(this.closeSlider.bind(this)); , но я хочу остановить распространение по некоторым элементам, поэтому я запустил: btn.not('.wrapper').click(this.closeSlider.bind(this)); и затем внутри функции closeSlider у меня есть event.stopPropagation() прямо вверху, почему это не работает?

5. Событие анализируется правильно, когда я его регистрирую, но я думаю, что команда not игнорируется?

Ответ №2:

Вместо того, чтобы просто добавлять строку к телу, создайте живой элемент с помощью события onclick document.createElement и присоедините его к событию onclick, прежде чем выпускать его в открытый доступ.

Вот пример:

 function slider() {
    this.init = function(options, title, content) {
        var myButton = document.createElement("button");
        myButton.setAttribute("type", "button");
        myButton.innerHTML = title;
        myButton.onclick = this.closeSlider;

        $('body').append(myButton);
    },
    //Other object definitions
}
 

Комментарии:

1. могу ли я тоже это сделать? $("<button />").attr({'onclick':this.closeSlider,'type': 'button'});

2. @ShannonHochkins: Нет, .attr устанавливает атрибут элемента DOM. Значения атрибутов представляют собой строки .

3. Я бы не стал этого предлагать. Вы должны следовать сообщению @Patrick Evans для правильной реализации jQuery.

4. это назначение onclick не будет работать; оно теряет контекст.

5. @Eevee Внутри this.init функции, разве контекст по-прежнему slider не является экземпляром? Если нет, я удалю свой пост, поскольку вы правы, это неверное решение.

Ответ №3:

Прежде всего, вы должны добавлять методы в прототип, а не в каждый экземпляр (экономит память).

Во-вторых, вы можете использовать jQuery .proxy() для создания анонимной функции, которая будет «привязывать» это к определенному значению при вызове вашего метода.

 // empty constructor
function slider() 
{
}

// define prototype
$.extend(slider.prototype, {
    init: function(options, title, content) {
        $('<button>', { text: title })
            .on('click', $.proxy(this, 'closeSlider'))
            .appendTo('body');
    },
    create: function(title, content, options) {
        this.init(options, title, content);
    },
    closeSlider: function(event) {
        // event.target is the HTML element
        this.assignPositions(event.target);
    },
    assignPositions: function(elem) {
        alert('assign positions called from button?');
    }
});
 

Комментарии:

1. Но, допустим, у меня есть переменные внутри экземпляра, как я могу получить к ним доступ с помощью прототипа?

2. @ShannonHochkins Вы можете объявлять свойства в своих экземплярах, к которым могут быть доступны все методы; т.е. this.foo = 'bar'; .

3. Но вне метода, как и до того, как я вызывал var slider = new slider() ; затем оттуда я могу получить доступ ко всем переменным, например: slider.vars.settings

4. затем доступ к методам с помощью slider.create();

5. @ShannonHochkins Правильно, так что внутри slider.create() вы могли бы связаться с ними через this.vars.settings .