自定义Javascript库:为动态添加的html添加事件监听器

Custom Javascript library: Add event listener to dynamically added html

本文关键字:添加 html 事件 监听器 动态 Javascript 自定义      更新时间:2023-09-26

我正在尝试构建一个像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);

但是我不确定如何实现这个监听器。

请帮助。

从你的评论我想你要求一个实时实现?

如果是这种情况,我建议你添加一个数据方法到你的对象,记住所有的事件要注册,并从append方法注册它们,当内容被附加到当前元素。

我用。data和。live方法扩展了您的库,并为下一个要添加到body中的span排队注册事件。请参阅修改后的代码片段,并签出控制台进行验证。

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方法
  • 做一个类似的实现
  • 如果你想做一个真正的活克隆,你将不得不保留预先注册的事件定义,并注册任何与选择器匹配的新元素(此时,一旦一个元素匹配了选择器,事件被注册,事件定义在追加中被删除-为了使它通用,你将不得不标记你的绑定元素,为此使用数据)