自定义 Javascript 库:添加事件侦听器以动态添加 html
Custom Javascript library: Add event listener to dynamically added html
我正在尝试构建一个类似于 jQuery 的 Javascript 库,只是为了学习更多 Javascript。到目前为止,我已经开发了这个:
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
对于方法,我开发了一些类似的方法:
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
console.log(window.event);
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html();
this.html(old + '' + value);
return this;
}
};
您可能已经注意到我定义了一个方法 on
,例如 jQuery。
每当我像 jsLib('div#foo').on('click', someFunc);
一样打电话时,它工作正常。
但是,假设我附加了一些 html,例如 jsLib('body').append('<a id="#bar" href="#">Click</a>');
然后我想提供一个 API 来向 #bar
添加事件侦听器,例如 jsLib('body').on('click', '#bar', someOtherFunc);
。
但我不确定如何实现此侦听器。
请帮忙。
根据您的评论,我想您是在请求实时实施吗?
如果是这种情况,我建议您向对象添加一个数据方法,记住所有要注册的事件,并在内容附加到当前元素时通过追加方法注册它们。
我使用 .data 和 .live 方法扩展了您的库,并为要添加到正文中的下一个跨度排队了一个事件注册。查看修改后的代码片段并检查控制台以进行验证。
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
this._selector = selector;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html(),
pendingEvents = this.data('jsLib_Future_Events') || [],
registered = {};
this.html(old + '' + value);
// Attach pending events to newly added childs (if any match found)
pendingEvents.forEach(function (evConf, i) {
[].slice.call(jsLib(this._selector + ' ' + evConf.selector), 0).forEach(function (el) {
jsLib(el).on(evConf.type, evConf.callback);
registered[i] = true;
});
}.bind(this));
// Clear list of pending requests of any registered events
this.data('sLib_Future_Events', pendingEvents.filter(function (evConf, i) { return !!registered[i]; }));
return this;
},
_data: {},
data: function (key, value) {
if (arguments.length > 1) this._data[key] = arguments[1]; // Setter
return key ? this._data[key] : this._data; // Getter of key or all
},
live: function (type, selector, callback) {
this.data('jsLib_Future_Events', (this.data('jsLib_Future_Events') || []).concat({type: type, selector: selector, callback: callback}));
return this;
}
};
jsLib('body').live('click', 'span', function () { console.debug('event triggered on appendend content after live registration of event handle'); });
jsLib('body').append('<br><span>dynamic content</span>');
<div>existing content</div>
注意事项:
- 您必须对 html 方法进行类似的实现
- 如果你想制作一个真正的实时克隆,你将必须保留预先注册的事件定义并注册任何与选择器匹配的新元素(此时一旦元素与选择器匹配并且事件被注册事件定义在追加中被删除 - 为了使其通用,你必须标记你的绑定元素,为此使用数据)
我正在尝试构建一个类似于 jQuery 的 Javascript 库,只是为了学习更多 Javascript。到目前为止,我已经开发了这个:
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
对于方法,我开发了一些类似的方法:
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
console.log(window.event);
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html();
this.html(old + '' + value);
return this;
}
};
您可能已经注意到我定义了一个方法 on
,例如 jQuery。
每当我像 jsLib('div#foo').on('click', someFunc);
一样打电话时,它工作正常。
但是,假设我附加了一些 html,例如 jsLib('body').append('<a id="#bar" href="#">Click</a>');
然后我想提供一个 API 来向 #bar
添加事件侦听器,例如 jsLib('body').on('click', '#bar', someOtherFunc);
。
但我不确定如何实现此侦听器。
请帮忙。
根据您的评论,我想您是在请求实时实施吗?
如果是这种情况,我建议您向对象添加一个数据方法,记住所有要注册的事件,并在内容附加到当前元素时通过追加方法注册它们。
我使用 .data 和 .live 方法扩展了您的库,并为要添加到正文中的下一个跨度排队了一个事件注册。查看修改后的代码片段并检查控制台以进行验证。
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
this._selector = selector;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html(),
pendingEvents = this.data('jsLib_Future_Events') || [],
registered = {};
this.html(old + '' + value);
// Attach pending events to newly added childs (if any match found)
pendingEvents.forEach(function (evConf, i) {
[].slice.call(jsLib(this._selector + ' ' + evConf.selector), 0).forEach(function (el) {
jsLib(el).on(evConf.type, evConf.callback);
registered[i] = true;
});
}.bind(this));
// Clear list of pending requests of any registered events
this.data('sLib_Future_Events', pendingEvents.filter(function (evConf, i) { return !!registered[i]; }));
return this;
},
_data: {},
data: function (key, value) {
if (arguments.length > 1) this._data[key] = arguments[1]; // Setter
return key ? this._data[key] : this._data; // Getter of key or all
},
live: function (type, selector, callback) {
this.data('jsLib_Future_Events', (this.data('jsLib_Future_Events') || []).concat({type: type, selector: selector, callback: callback}));
return this;
}
};
jsLib('body').live('click', 'span', function () { console.debug('event triggered on appendend content after live registration of event handle'); });
jsLib('body').append('<br><span>dynamic content</span>');
<div>existing content</div>
注意事项:
- 您必须对 html 方法进行类似的实现
- 如果你想制作一个真正的实时克隆,你将必须保留预先注册的事件定义并注册任何与选择器匹配的新元素(此时一旦元素与选择器匹配并且事件被注册事件定义在追加中被删除 - 为了使其通用,你必须标记你的绑定元素,为此使用数据)