Есть ли ненавязчивый способ подключиться к методам jQuery для триггеров?

Мне было интересно, есть ли какой-нибудь ненавязчивый способ подключиться к таким методам, как attr, data, css и т. д., И вызвать настраиваемые триггеры?

В идеале я мог бы сделать что-то вроде этого:

$(".friend a").bind("attr.changed", changed /* data */, function(e) {
    alert("The " + changed.attribute + " attribute changed from " + changed.from + " to " + changed.to + "!");
});

$(".friend").append(
  $("<a/>").
    attr("href", "#").
    html("Friend 1").
    click(function() { alert('I was clicked!'); }); // creates the element, doesn't execute since element didn't exist

$(".friends a").each(function() {
  var $this = $(this);
  $this.attr("rel", "friend"); // triggers "attr.changed"
});

В идеале это можно было бы запускать для любого элемента и передавать измененный attr, from и to в объекте, в вызов триггера изнутри каждого метода jQuery.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
1 251
5

Ответы 5

Для этого в jQuery нет события.

плагин livequery может предоставить что-то из того, что вам нужно, например, изменение классов. В основном селектор сохраняется, а затем любые изменения в DOM, которые меняют то, что влияет на селектор, затем вызывают переданные функции и т. д.

И почему бы вам не воспользоваться самым простым подходом:

jQuery.fn.changeAttr = function(attrName,attrValue) {
  return this.each(function(){
    this.attr(attrName,attrValue);
    alert('The att: '+attrName+ ' is now '+attrValue);
  });
};

А потом просто:

$('.friends a').changeAttr('rel','friend')

Извините, если это не сработает, я точно не помню синтаксис расширения jQuery.

Вот модификация attr() в соответствии с тем, о чем вы говорите.

(function(attr) {

    jQuery.attr = function(elem, name, value) {
        var current = attr(elem, name, undefined); // read current value
        var retval = current;

        if (value !== undefined) { // writing
            retval = attr(elem, name, value); // call original
            jQuery.event.trigger('attr.changed', {
                attribute: name,
                from: current,
                to: value
            }, elem)
        }

        return retval; // return original
    }

})(jQuery.attr);

Использование должно быть:

$(".friend a").bind("attr.changed", function(e, changed) {
    alert("The " + changed.attribute + " attribute changed from " + changed.from + " to " + changed.to + "!");
});

$(".friends a").attr("class", "foo"); // triggers alert

Я не верю, что css() возможен, поскольку свойство .style не может запускать события. data() Не знаю.

Обратите внимание, я не оправдываю его использования, это было всего лишь академическим усилием. То, что вы хотите, приводит к снижению производительности на attr(), чтобы заполнить свойство from аргумента события. Мы должны прочитать старое значение, прежде чем записывать новое.

Написать функцию "перехвата" довольно просто:

function hook(original, wrapper) {
    return function() {
        wrapper.apply(this, arguments);
        return original.apply(this, arguments);
    }
}

Предоставленная вами функция wrapper будет вызываться с теми же аргументами, что и функция original, до вызова самой исходной функции.

Пример использования:

$.fn.attr = hook($.fn.attr, function(attribute, value) {
    alert('attribute: '+attribute+', value: '+value);
});
$('a.pie').attr('href', 'http://blueberry.pie');
// An alert says "attribute: href, value: http://blueberry.pie"

(Примечание: было бы простым расширением позволить вашему wrapper также отменить вызов функции original, но это становится более функциональным, чем вы хотели.)

Вы можете использовать это напрямую, чтобы делать то, что хотите, или вы можете заставить функцию wrapper просто запускать пользовательские события jquery, которые вы прослушиваете стандартными способами jquery.

Этот плагин существует, но с немного другим api: github.com/aheckmann/jquery.hook/blob/master/jquery.hook.js

Jerph 01.11.2010 20:30

Оказывается, этот прием сработает; Я использую встроенные в данные триггеры setData (и вышеупомянутую «ловушку» для добавления функциональности поверх attr и removeAttr jQuery) для дублирования атрибутов в объекте данных в объекте jQuery. Хотя это несколько грязно, у меня есть возможность подключаться к триггерам изменения данных для data, attr и, если они написаны, любых других методов jQuery, которые отслеживают пары ключ / значение.

(function($) {
  var binder = function(e, dataKey, dataValue) {
    return (function(dataKey, dataValue, self) {
      var $this = $(self),
          oldValue = $this.data(dataKey),
          newValue = dataValue,
          passed = {
            attr: dataKey,
            from: oldValue,
            to:   newValue
          };

      var isAttribute = !!($this.data(dataKey + "-attribute"));

      if (oldValue !== newValue) { 
        var attrPrefix = isAttribute ? "attr-" : "";
        $this.trigger(attrPrefix + dataKey + "-changed", passed); 
        $this.trigger(attrPrefix + "data-changed", passed); 
      }
    })(dataKey, dataValue, this);
  };

  var hook = function(original, wrapper) {
    return function() {
      wrapper.apply(this, arguments);
      return original.apply(this, arguments);
    };
  };

  $.fn.attr = hook($.fn.attr, function(attr, val) {
    if (val) {
      $(this).data(attr + "-attribute", true);
      $(this).data(attr, val);
    }
  });

  $.fn.removeAttr = hook($.fn.removeAttr, function(attr) {
    $(this).removeData(attr + "-attribute");
    $(this).removeData(attr);
  });

  $.fn.observeData = function() {
    $(this).bind("setData", binder);
  };
})(jQuery);

Другие вопросы по теме