-1

我正在尝试构建一个像 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);时,它工作正常。

但是,假设我附加了一些像jsLib('body').append('<a id="#bar" href="#">Click</a>');

然后我想提供一个 API 来将事件监听器添加到#barlike jsLib('body').on('click', '#bar', someOtherFunc);

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

请帮忙。

4

1 回答 1

0

从您的评论中,我想您要求实时实施?

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

我使用 .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 方法做一个类似的实现
  • 如果您想进行真正的实时克隆,则必须保留预先注册的事件定义并注册与选择器匹配的任何新元素(此时,一旦元素与选择器匹配并且事件已注册,则事件定义将在附加中删除 -为了使其通用,您必须标记您的绑定元素,为此使用数据)
于 2015-10-28T20:45:32.130 回答