前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我现在写jquery,你们会不会打我??

我现在写jquery,你们会不会打我??

作者头像
王小婷
修改2020-11-19 14:38:28
4400
修改2020-11-19 14:38:28
举报
文章被收录于专栏:编程微刊编程微刊
时光荏苒,岁月如梭,转眼多年过去。前端天下已各分东西,回眸看看来时的路,你我可曾记得当年的大哥 jquery。回想那个纯真的年代,jquery一统天下,前端的世界如此纯洁无瑕。

引子

此时此刻又让我想起了当年的游戏时光,早期游戏只能玩类似《传奇》《魔力宝贝》这么些。大家没得选所有人都会玩这么几款游戏,随着时间推移现在游戏越来越多,忽然发现可以玩的游戏却少了,前端世界也是如此,框架技术层出不穷,很多前端同学开始争论哪种技术更强,哪种框架更6,其实大可不必。如同现在玩游戏一样 ,我们找的只是当年的那份快乐,玩什么游戏其实已经并不关键。技术亦如此,我们需要了解的是各种技术背后的东西,本质的东西,例如思路、理念,原理实现等等。到这,为引子。

好了上面那些废话是今天的引子,今天咋们需要做的是通过jq来看看这个框架背后的东西,学习jq主要功能实现原理,供今后实际开发中学习和借鉴。

jquery选择器实现

jquery在设计之初都是围绕着核心思想write less do more来设计的。整体使用思路与原生js没有太大区别,所以jquery做的最多的一件事情就是简化原生js的代码量。选择器在操作dom上使用非常频繁,所以jq一定会简化选择器使用方式。原生选择器使用如下:

代码语言:javascript
复制
document.querySelector(".box")

恩这里声明下,js用最新语法形式,不去考虑兼容性问题。jq的简化操作如下:

代码语言:javascript
复制
$(".box")

发现代码量变短了,这里是一行,那如果项目里有很多呢?是不是就write less了?有木有?恩,到这,jquery 是基于js来实现的 ,那么我们如何用原生js来实现一个选择器封装呢?🤔one thousand years later....!代码如下:

代码语言:javascript
复制
  function $(args){      return document.querySelector(args);  }

$当成一个函数来定义可以轻松简化原生的选择器。

实现click方法

但是细想,无论是js选择器还是jquery选择器都是需要来获取节点进行操作的。所以你会发现,我们这样定义没办法后续操作了。我们以click操作作为案例来瞅一下。如下:

代码语言:javascript
复制
//原生js  document.querySelector(".box").onclick = function(){     console.log("点击了,老铁"); } //jquery操作  $(".box").click(()=>{     console.log("点击了,老铁"); })

恩 为此我们可以优化一下 ,🤔one thousand years later....!代码如下:

代码语言:javascript
复制
class Jq{ constructor(args){     let ele = document.querySelector(args);     this.ele = ele; }    click(fn){     this.ele.onclick = fn; }}
function $(args){ return new Jq(args);}

如上这样 我们就可以通过调用实现类似jquery的click调用形式。如下:

代码语言:javascript
复制
 $(".box").click(()=>{      console.log("点击了,老铁");  })

这个时候发现实现一个click并没有什么难度。

选择器多种情况判断

上面我们实现了简版的功能接下来看下,jquery选择器里会有更多情况,如下情况: 情况一:

代码语言:javascript
复制
$(".box") //传入 id、类名、标签名

情况二:

代码语言:javascript
复制
$(function(){  console.log("dom结构加载完毕后钩子")}

情况三:

代码语言:javascript
复制
$(document.querySelector(".box"))  //传入原生节点对象

恩,针对上述分析情况,且要考虑获取多个节点的情况。咋们来扩充下对应的封装,🤔one thousand years later....!代码如下:

代码语言:javascript
复制
class Jq{ constructor(args){     if(typeof args==="string"){         let eles = document.querySelectorAll(args);         this.addEles(eles);     }else if(typeof args==="function"){         document.addEventListener("DOMContentLoaded",args);     }else{         if(typeof args.length==="undefined"){             this[0] = args;             this.length = 1;         }else{             this.addEles(args);         }     } }    addEles(eles){     for(let i=0;i<eles.length;i++){         this[i] = eles[i];     }     this.length = eles.length; } click(fn){     this.ele.onclick = fn; }}

这样完成了多种情况的判断及处理,针对多种情况调用我们需要做的其实是查找多种功能之间的差异性,通过差异来区分判断就好了。上述代码为了方便后面对于节点的操作,我会把一个或者多个节点绑定在this对象上,为后面的使用做铺垫。

on方法实现

on方法和click方法非常类似,只是click是单一方法,on是可以绑定多个方法。So,可以在这个基础上扩展on方法即可。代码如下:

代码语言:javascript
复制
 on(eventName,fn){       for(let i=0;i<this.length;i++){           this[i].addEventListener(eventName,fn);       }   }

恩,上述方法没有过多需要强调的,比较简单。

eq方法实现

在jquery中有些比较有特点的方法。比如eq ,可以选择具体哪个节点来进行操作。通过eq方法也可以看到现在经常在前端中见到的链式操作。eq使用代码如下:

代码语言:javascript
复制
$("div").eq(1).on("click",()=>{     console.log(123)})

上述代码,选择了第二个节点绑定了点击方法。$("div").eq(1).on(eventName,cb),链式操作的写法和管道使用异曲同工。由于eq选择节点之后会有后续链式操作,所以我们内容应该如下实现:

代码语言:javascript
复制
   eq(index){       return new Jq(this[index]);   }

通过返还一个新的jq对象实现调用时候的链式调用。

end方法实现

恩,有个方法和eq非常类似。eq可以选择具体要操作哪个节点。通过可以通过end方法返还上次操作节点,如果开始并没有上次操作的节点就会返回[document]默认节点。那么在内容我们 应该如何实现呢 ?思路是这样的,在每次eq之后我们可以通过某个变量记录上次操作的节点。🤔one thousand years later....!代码如下:

代码语言:javascript
复制
if(typeof root !== "undefined"){     //调取eq时候 传入 root  作为上次操作节点     this.prevObj = root; }else{  //如果没有上次操作节点 ,默认保存document     this.prevObj = [document]; }

调用eq的时候传入上次操作的节点,通过prevObj来保存起来。

代码语言:javascript
复制
//当前this就是本次操作的对象  eq(index){       return new Jq(this[index],this);   }

css 方法实现

在jquery对外暴露$对象下会有很多的方法,其实思路都是分析如何调用,通过调用来推测其内部结构。如同通过需求及功能来写具体代码。先实现通用功能,然后在分析不同情况来区分处理,如同产品的更新迭代。css方法在jquery设计之初比较有特点,不仅仅提供了各种api的调用,还基础未来。先分析一波 css方法如何使用,通过调用来实现其功能: 调用方式一:

代码语言:javascript
复制
let res =  $("div").css("background"); console.log(res);

返还css获取的样式值,即使有多个节点依然返还第一个节点的css样式 调用方式二:

代码语言:javascript
复制
$("div").css("background","blue");

设置css样式,接收2个参数。调用方式三:

代码语言:javascript
复制
$("div").css({"background":"blue","width":200})

同样设置样式,可以设置多个样式。且对于 样式“px”单位做了容错处理。

针对上述分析,区分各种情况,代码实现如下:

代码语言:javascript
复制
 css(...args) {       if (args.length === 1) {           if (typeof args[0] === "string") {               return this.getStyle(this[0], args[0]);           } else {               for (let i = 0; i < this.length; i++) {                   for (let j in args[0]) {                       this.setStyle(this[i], j, args[0][j]);                   }               }           }       } else {           for (let i = 0; i < this.length; i++) {               this.setStyle(this[i], args[0], args[1]);           }       }       return this;   }   getStyle(ele, styleName) {       return window.getComputedStyle(ele, null)[styleName]   }   setStyle(ele, styleName, styleValue) {       if (typeof styleValue === "number") {           styleValue = styleValue + "px"       }       ele.style[styleName] = styleValue;   }

恩上述代码更多的就是组织逻辑,没有过多需要强调的。需要提一嘴的就是不定参的处理,用了ES6中的rest和链式调用的另一种写法返还this对象。

$.cssNumber扩展

上述的css方法可以实现获取及设置css样式的特性。其中有个小小的细节。就是样式的值如果是number类型 会自动加上“px”单位 。但是细想下是不是所有的css样式是number类型的都需要 加上单位呢?答案是否定的,例如zoom、opacity、flexGrow等等 都是不需要加“px”单位的,所以我们可以弄一个配置列表来将不需要加单位css属性储存起来。如下做法:

代码语言:javascript
复制
let cssNumber = {   animationIterationCount: true,   columnCount: true,   fillOpacity: true,   flexGrow: true,   flexShrink: true,   fontWeight: true,   gridArea: true,   gridColumn: true,   gridColumnEnd: true,   gridColumnStart: true,   gridRow: true,   gridRowEnd: true,   gridRowStart: true,   lineHeight: true,   opacity: true,   order: true,   orphans: true,   widows: true,   zIndex: true,   zoom: true}// css方法容错的时候可以加上如下判断if (typeof styleValue === "number") {     if(!(cssNumber[styleName])){         styleValue = styleValue + "px"     } }

如上就 可以排除不需要加单位的一些css属性。但是,如果直接定义一个对象,那么cssNumber的扩展性就不是那么强了,假如未来会有新的css属性出现然而jq没有收录,那么jq就没有 办法用了。为此 我们可以将cssNumber 挂在$上,这样外部就可以对cssNumber做对应的扩展了!!如下:

代码语言:javascript
复制
$.cssNumber = {  animationIterationCount: true,  columnCount: true,  fillOpacity: true,  flexGrow: true,  flexShrink: true,  fontWeight: true,  gridArea: true,  gridColumn: true,  gridColumnEnd: true,  gridColumnStart: true,  gridRow: true,  gridRowEnd: true,  gridRowStart: true,  lineHeight: true,  opacity: true,  order: true,  orphans: true,  widows: true,  zIndex: true,  zoom: true}

细品一下jquery,也是会得到 一些新的感悟与思路。白驹过隙,忽然而已。技术更迭,轮子层出不穷,唯一不变的是JavaScript,同样也是各种轮子背后的东西,和从前的那个少年!!(我还是从前 那个少年没有一丝丝改变......啦啦啦);

你可以 默默看过,也可以悄悄点赞,还可以高调关注!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 时光荏苒,岁月如梭,转眼多年过去。前端天下已各分东西,回眸看看来时的路,你我可曾记得当年的大哥 jquery。回想那个纯真的年代,jquery一统天下,前端的世界如此纯洁无瑕。
  • 引子
    • 此时此刻又让我想起了当年的游戏时光,早期游戏只能玩类似《传奇》《魔力宝贝》这么些。大家没得选所有人都会玩这么几款游戏,随着时间推移现在游戏越来越多,忽然发现可以玩的游戏却少了,前端世界也是如此,框架技术层出不穷,很多前端同学开始争论哪种技术更强,哪种框架更6,其实大可不必。如同现在玩游戏一样 ,我们找的只是当年的那份快乐,玩什么游戏其实已经并不关键。技术亦如此,我们需要了解的是各种技术背后的东西,本质的东西,例如思路、理念,原理实现等等。到这,为引子。
    • 好了上面那些废话是今天的引子,今天咋们需要做的是通过jq来看看这个框架背后的东西,学习jq主要功能实现原理,供今后实际开发中学习和借鉴。
    • jquery选择器实现
    • 实现click方法
    • 选择器多种情况判断
    • on方法实现
    • eq方法实现
    • end方法实现
    • css 方法实现
    • $.cssNumber扩展
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档