jQuery插件也适用于动态创建的元素

我正在编写一个jquery插件,它应该处理指定开放行为的链接的额外信息。

例如,我想支持标记,如:

第一个应该在新窗口中打开,第二个应该在模式对话框中打开,第三个应该以本机行为打开(无论在标签上设置了什么目标)。

我想为这种行为创建一个尽可能通用的插件。 我现在写的:

 (function ($) { $.fn.myOpenMode = function () { return this.mousedown(function () { var $this = $(this); var mode = $this.data("openmode"); var href = this.href; var handled = true; if (mode) { switch (mode) { case "NewWindow": case "1": window.open(href, "_blank"); break; case "Dialog": case "2": openAsDialog(href); break; // Actually, there are other options, but I removed them for clarity default: handled = false; } } else { handled = false; } return !handled; }); }; })(jQuery); 

这段代码允许我从任何页面调用类似于:

 $(function(){ $(".openmode").myOpenMode(); }); 

这适用于静态生成的标记。 但是,我的应用程序可能会动态生成标记(大部分时间使用jsRender,但这并不重要)。

但是因为在加载javascript文件时会设置一次此行为,所以它不会采用动态生成的对象。

我该怎么做来处理我的要求?

  1. 我试图使用on方法来监视加载事件,但这不起作用:

     $(function(){ $(document).on("load",".openmode", function() { $(this).myOpenMode(); }); }); 

    我明白这不起作用,因为“加载”事件不起泡

  2. 我正在考虑修改我的插件以在插件中放置“on”,但我不喜欢这个想法,因为它在插件中引入了一些超出范围的行为

  3. 我也可以在每次创建动态节点时调用插件,但它也会将依赖项引入其他部分。 我的插件不会像我想的那样自主。

有没有人有建议来处理我的要求,让我的插件尽可能隔离?

[编辑]这应该适用于IE8及更高版本(理想情况下与其他浏览器一起使用)

[编辑]这里是一个说明问题的jsFiddle (只需单击Add并尝试单击新创建的元素)。

添加到$.fn插件应仅适用于列出的元素,而不适用于任何将来的元素。

您应该专注于让插件提供机制 ,例如:

 (function($) { $.fn.openmode = function(cmd) { cmd = cmd || 'on'; switch (cmd) { case 'click': // read props, open windows, etc break; case 'on': this.addClass('openmode'); break; case 'off': this.removeClass('openmode'); break; } }); })(jQuery); 

然后允许插件用户注册触发该机制的事件处理程序,必要时使用事件委托:

 $(document).on('click', 'a.openmode', function() { $(this).openmode('click'); }); 

后一个代码也可以作为实用函数放入jQuery命名空间:

 (function($) { $.openmode = function(cmd) { cmd = cmd || 'on'; switch (cmd) { case 'on': $(document).on('click.openmode', 'a.openmode', function() { $(this).openmode('click'); }); break; case 'off': $(document).off('click.openmode', 'a.openmode'); break; } }; })(jQuery); 

这样只是打电话:

 $.openmode(); 

将完成为每个当前(和未来) .openmode元素启用插件所需的所有工作。

我迟到了,但希望它对某人有帮助。 我有同样的问题。

 $.fn.plugin = function(){ //some code } $(".element").plugin(); //works fine $(".elementParent").append(".newElement"); $(".newElement").plugin(); // doesn´t work 

它不起作用,因为你需要在添加元素后再次调用插件,就像这样

 function runPlugin(){ $.fn.plugin = function(){ //some code } } runPlugin(); //call plugin here $(".element").plugin(); //works fine $(".elementParent").append(".newElement"); runPlugin(); // call plugin here $(".newElement").plugin(); // works fine 

我在插件中找到了依赖on on()方法的解决方案 。

在这种情况下,插件等待selector参数仍然将选择器保持在应用程序级别(而不是插件级别):

 (function ($) { $.fn.myOpenMode = function (selector) { return $(document).on("mousedown", selector ,function () { var $this = $(this); var mode = $this.data("openmode"); var href = this.href; var handled = true; if (mode) { switch (mode) { case "NewWindow": alert("NewWindow"); break; case "Dialog": alert("Dialog"); break; default: handled = false; } } else { handled = false; } return !handled; }); }; })(jQuery); 

然后,我必须将调用更改为我的插件:

 $(function(){ $.fn.myOpenMode(".openmode"); }); 

按预期工作的。 但是,我对尊重jQuery插件指南并不十分自信。

因此,如果有人有更好的解决方案,我会很高兴知道。

你仍然可以实现自己的观察者方法,这里扩展了append方法:

 ;(function ($) { var fctsToObserve = { append: [$.fn.append, 'self'] }, fctsObserveKeys = ''; $.each(fctsToObserve, function (key, element) { fctsObserveKeys += "hasChanged." + key + " "; }); var oOn = $.fn.on; $.fn.on = function () { if (arguments[0].indexOf('hasChanged') != -1) arguments[0] += " " + fctsObserveKeys; return oOn.apply(this, arguments); }; $.fn.hasChanged = function (types, data, fn) { return this.on(fctsObserveKeys, types, null, data, fn); }; $.extend($, { observeMethods: function (namespace) { var namespace = namespace ? "." + namespace : ""; var _len = $.fn.length; delete $.fn.length; $.each(fctsToObserve, function (key) { var _pre = this; $.fn[key] = function () { var target = _pre[1] === 'self' ? this : this.parent(), ret = _pre[0].apply(this, arguments); target.trigger("hasChanged." + key + namespace, arguments); return ret; }; }); $.fn.length = _len; } }); $.observeMethods() })(jQuery); 

应该也可以在旧的浏览器中使用,但是,观察者遇到了一些性能问题,即使你可以优化它。

看看演示

您可以使用所谓的Mutation Observer方法来响应DOM中的更改。 以下是有关它的更多信息:

MutationObserver

以下是一些很好的例子:

DOM操作