是否有任何不引人注目的方式来挂钩触发器的jQuery方法?

时间:2009-01-13 18:01:22

标签: javascript 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传递给每个jQuery方法内部的触发器调用。

5 个答案:

答案 0 :(得分:7)

编写“钩子”函数非常容易:

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事件。

答案 1 :(得分:1)

原来这个黑客会起作用;我使用数据的内置setData触发器(以及前面提到的'hook'来在jQuery的attr和removeAttr上添加功能)来复制jQuery对象上的数据对象中的attrs。虽然它有点脏,但我得到的功能是挂钩数据,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);

答案 2 :(得分:0)

jQuery中目前没有此事件。

livequery plugin可能会提供您所需要的内容,例如更改课程。基本上保存了选择器,然后DOM中任何改变选择器影响的更改都会调用传递的函数等。

答案 3 :(得分:0)

为什么不使用最简单的方法:

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的语法。

答案 4 :(得分:0)

这是对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属性。在编写新值之前,我们必须先读取旧值。