手写一个mini版jquery
我们要实现的功能如下
1.执行结构
2.amd模块检测
3.整体架构搭建
4.原型方法添加
5.全局方法添加
执行结构与amd模块检测
//amd模块检测 if (typeof define === 'function' && define.amd){ define(definition); } //执行结构 var $ = jQuery = (function(window,undefined){ })(window)
整体架构搭建
// 对dom集合进行存储,生成jquery对象 function Query(dom, selector){ // 通过遍历dom集合,将el注入this实例 => Z函数的实例 let i, len = dom ? dom.length : 0 for (i = 0; i < len; i++) this[i] = dom[i] this.length = len this.selector = selector || '' return this; } // 进行dom查看,同时生成jquery对象 function Z(elements, selector){ return Query.call(this, elements, selector) } // 具体的dom查找 function qsa(element, selector){ // 暂时不考虑选择器的其它情况 return element.querySelectorAll(selector) } // 得到jquery对象 return function(nodeSelector){ let doms = qsa(document, nodeSelector) // debugger; return new Z(doms, nodeSelector); }
原型方法添加
Z.prototype = { each(callback){ // [].every 是es5的数组原型方法,用于循环,返回值为布尔值(循环的内容必须都满足,才会返回true,否则返回false) [].every.call(this, function(el, index){ return callback.call(el, index, el) !== false }) }, // 查找元素 find(selector){ let doms = [] this.each(function(index, el){ let childs = this.querySelectorAll(selector); doms.push(...childs); }) //为了实现链式操作 返回当前对象 return new Z(doms, selector); }, //增加样式 addClass:function (classes){ let className = classes.split(' '); className.forEach(value => { this.each(function(index,el){ el.classList.add(value); }) }); return this; }, //比较第几个 eq(i){ let doms = []; this.each(function(index, el){ if(i == index) { doms.push(this); } }) //为了实现链式操作 返回当前对象 return new Z(doms, this.selector); }, //删除方法 remove(){ this.each(function(index, el){ this.remove(); }) } }
全局方法添加
// 定义全局方法(既可以内部使用) function isFunction(value) { return typeof value == "function" } function isWindow(obj) { return obj != null && obj == obj.window } function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE } function $(nodeSelector){ let doms = qsa(document, nodeSelector) return new Z(doms, nodeSelector); } // 定义zepto的全局方法(也可以外部使用) $.isFunction = isFunction; $.isWindow = isWindow; $.isDocument = isDocument; // 得到jquery对象 return $
完整代码
//amd模块检测 if (typeof define === 'function' && define.amd){ define(definition); } var $ = jQuery = (function(window,undefined){ // 对dom集合进行存储,生成jquery对象 function Query(dom, selector){ // 通过遍历dom集合,将el注入this实例 => Z函数的实例 let i, len = dom ? dom.length : 0 for (i = 0; i < len; i++) this[i] = dom[i] this.length = len this.selector = selector || '' return this; } // 进行dom查看,同时生成jquery对象 function Z(elements, selector){ return Query.call(this, elements, selector) } // 具体的dom查找 function qsa(element, selector){ // 暂时不考虑选择器的其它情况 return element.querySelectorAll(selector) } Z.prototype = { each(callback){ // [].every 是es5的数组原型方法,用于循环,返回值为布尔值(循环的内容必须都满足,才会返回true,否则返回false) [].every.call(this, function(el, index){ return callback.call(el, index, el) !== false }) }, find(selector){ let doms = [] this.each(function(index, el){ let childs = this.querySelectorAll(selector); doms.push(...childs); }) return new Z(doms, selector); }, addClass:function (classes){ let className = classes.split(' '); className.forEach(value => { this.each(function(index,el){ el.classList.add(value); }) }); return this; }, eq(i){ let doms = []; this.each(function(index, el){ if(i == index) { doms.push(this); } }) return new Z(doms, this.selector); }, remove(){ this.each(function(index, el){ this.remove(); }) } } // 定义全局方法(既可以内部使用) function isFunction(value) { return typeof value == "function" } function isWindow(obj) { return obj != null && obj == obj.window } function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE } function $(nodeSelector){ let doms = qsa(document, nodeSelector) return new Z(doms, nodeSelector); } // 定义zepto的全局方法(也可以外部使用) $.isFunction = isFunction; $.isWindow = isWindow; $.isDocument = isDocument; // 得到jquery对象 return $ })(window)
FAQ
实现的功能,优点,可扩展的地方:
1.给元素增加class
2.链式操作
3.需要什么可以在Z的原型方法里添加
4.jquery对象非常纯净,方法添加以及操作都在Z上
5.全局方法调用