骚气十足:自定义jQuery的全新方式

发表时间: 2019-05-08 15:08

那些年,我们一起"追"过的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.$)

简单测试一把:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name='viewport' content='width=750,user-scalable=no' /> <title>xQuery</title> <style> * { margin: 0; padding: 0; } #box{ width: 100px; height: 100px;; } </style></head><body> <div id='box'></div>  <script src='./xQuery.js'></script> <script> $('#box').css('background','red').css('height','400px').width('400px').tap(function () { alert(22) }, { responseTime: 220 }); $(function () { console.log('loaded'); }) </script></body></html>

知识点:

  1. 面向对象基础,我用的是es5的,完全可以使用ES6的 class 来实现。
  2. 怎么在类的原型上扩展方法。
  3. 通过return this 实现链式调用。
  4. 使用闭包,防止全局污染。然后对外暴露访问的入口。
  5. 类似jQuery对外提供$方法的,我们在$方法中实例化类。
  6. arguments的使用,注意会有和this一样的指向问题。
  7. ES6 ... 语法的使用。可以将nodeList快速转成数组。
  8. 类的原型里面记得要重新指向一下 constructor为当前的类。
  9. 插件的扩展完全可以放在闭包里面,形成保护,因为对外的方法是挂载到了类的对象elements上面了,这个已经对外有暴露。

写在最后:

通过现象看本质,以上的实现只是一个最最基础的JQuery了,真正的jquery,比这个复杂得多 。希望我的这个简单的JQ,能让大家对jquery内部原理有一个更深层次的认识。

如果你发现有以上什么不对的,请一定要告诉我,反正我也不会改。VX公众号:itmlgb,你值得拥有。