问题 jQuery插件也适用于动态创建的元素
我正在编写一个jquery插件,它应该处理指定开放行为的链接的额外信息。
例如,我想支持标记,如:
<a href="somewhere" data-openmode="NewWindow" class="openmode" />
<a href="somewhere" data-openmode="Modal" class="openmode" />
<a href="somewhere" class="openmode" /> <!-- Not specified -->
第一个应该在新窗口中打开,第二个应该在模式对话框中打开,第三个应该以本机行为打开(无论在标签上设置了什么目标)。
我想为这种行为创建一个尽可能通用的插件。我现在写的:
(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文件时会设置一次此行为,所以它不会采用动态生成的对象。
我该怎么做来处理我的要求?
我试着用 on
监视加载事件的方法,但这不起作用:
$(function(){
$(document).on("load",".openmode", function() { $(this).myOpenMode(); });
});
我明白这不起作用,因为“加载”事件不起泡
我正在考虑修改我的插件以在插件中放置“on”,但我不喜欢这个想法,因为它在插件中引入了一些超出范围的行为
我也可以在每次创建动态节点时调用插件,但它也会将依赖项引入其他部分。我的插件不会像我想的那样自主。
有没有人有建议来处理我的要求,让我的插件尽可能隔离?
[编辑] 这适用于IE8及更高版本(理想情况下适用于其他浏览器)
[编辑] 这里有一个 的jsfiddle 这说明了问题(只需点击 Add
并尝试单击新创建的元素)。
7095
2018-05-14 12:00
起源
答案:
插件添加到 $.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
元件。
8
2018-05-14 13:03
我迟到了,但希望它对某人有帮助。我有同样的问题。
$.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
2
2017-07-06 22:12
我发现了一个 解 依赖于 on()
方法,在插件中。
在这种情况下插件等待a 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插件指南并不十分自信。
因此,如果有人有更好的解决方案,我会很高兴知道。
1
2018-05-14 12:38
你仍然可以实现自己的观察者方法,这里扩展了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);
应该也可以在旧的浏览器中使用,但是,观察者遇到了一些性能问题,即使你可以优化它。
看看演示
1
2018-05-14 13:11
您可以使用所谓的Mutation Observer方法来响应DOM中的更改。以下是有关它的更多信息:
MutationObserver
以下是一些很好的例子:
DOM操作
0
2018-05-14 12:05