![ca58d7a3a493c541c0361ec5acf569db.png](https://i-blog.csdnimg.cn/blog_migrate/24c12845ce9d57d85582fea9f5f68061.jpeg)
那些年,我们一起"追"过的Jquery 一文中有说到jquery的基本原理和插件的相关理论,今天我们来简单的实现一下。
废话少说,先上代码:
(function(window,document){ function xQuery(args){ this.elements = []; if(typeof args === 'string'){//选择器 var firstStr = args.charAt(0);//获取字符选择的是第一个字符,# . switch (firstStr) { case '#'://id选择器 this.elements = [document.getElementById(args.substring(1))]; break; case '.'://类选择器 this.elements = [...document.getElementsByClassName(args.substring(1))]; break; default://标签选择器 this.elements = [...document.querySelectorAll(args)]; break; } } else if(typeof args === 'function'){ window.addEventListener('DOMContentLoaded',()=>{ args(); }); } } xQuery.prototype = { constructor: xQuery,//这里指定下constructor,因为这个是可改的,容易发生变化。 each(fn){ this.elements.forEach(fn); return this; }, css(){ if (arguments.length === 1) {//只有一个参数,就是获取css属性 //IE获取元素样式则用 this.elements.currentStyle来做处理,我这边就不处理了。 return window.getComputedStyle(this.elements[0], null)[arguments[0]]; } else if (arguments.length === 2) {//两个参数就是设置css了 var args = arguments; return this.each(function(el,i){ el.style[args[0]] = args[1]; }) } }, width(){ if (arguments.length === 0) { return window.getComputedStyle(this.elements[0], null)['width']; } else if (arguments.length === 1) { var args = arguments;//注意arguments 也有指向的问题哦 return this.each(function (el, i) { el.style['width'] = args[0]; }) } }, click(fn){ return this.each((el,i)=>{ el.addEventListener('click',(e)=>{ fn && fn(e); }); }) }, }; function $(args) { return new xQuery(args); } $.fn = xQuery.prototype; window.$ = $; window.xQuery = xQuery;})(window,document);//扩展插件。(function($){ $.fn.tap = function(fn,option){ var defaultOption = Object.assign({ responseTime: 120 },option); var startime =0,endtime =0; this.each((el,i)=>{ el.addEventListener('touchstart', function (e) { startime = new Date().getTime(); }); }) this.each((el, i) => { el.addEventListener('touchend', function (e) { endtime = new Date().getTime(); if (endtime - startime < defaultOption.responseTime) { fn && fn(); } }); }) return this; }})(window.$)
简单测试一把:
xQuery
知识点:
- 面向对象基础,我用的是es5的,完全可以使用ES6的 class 来实现。
- 怎么在类的原型上扩展方法。
- 通过return this 实现链式调用。
- 使用闭包,防止全局污染。然后对外暴露访问的入口。
- 类似jQuery对外提供$方法的,我们在$方法中实例化类。
- arguments的使用,注意会有和this一样的指向问题。
- ES6 ... 语法的使用。可以将nodeList快速转成数组。
- 类的原型里面记得要重新指向一下 constructor为当前的类。
- 插件的扩展完全可以放在闭包里面,形成保护,因为对外的方法是挂载到了类的对象elements上面了,这个已经对外有暴露。
写在最后:
通过现象看本质,以上的实现只是一个最最基础的JQuery了,真正的jquery,比这个复杂得多 。希望我的这个简单的JQ,能让大家对jquery内部原理有一个更深层次的认识。
如果你发现有以上什么不对的,请一定要告诉我,反正我也不会改。VX公众号:itmlgb,你值得拥有。
![4689c37855f4f9df3275d6123ee10347.png](https://i-blog.csdnimg.cn/blog_migrate/26bc864b302f5e21d82994ae134b7098.jpeg)