优秀的编程知识分享平台

网站首页 > 技术文章 正文

自定义一个"骚气"的jQuery

nanyue 2024-09-11 05:26:26 技术文章 4 ℃

那些年,我们一起"追"过的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,你值得拥有。

Tags:

最近发表
标签列表