周末没事自己撸一个简易的Jquery库吧
说到JQuery,相信大家肯定很不陌生,很多人都将Jquery归为JS框架一类,其实Jquery是属于库,所谓的JS库就是用原生的JS作为底层去构建的,其中并没有其他第三方库的依赖,有的人说都什么时代了还说JQuery,俗话说的好:“不忘初心,成事之根本”,JQuery也是当初非常火的一个库,对于某些公司来说现在的技术栈中还是存在着Jquery。于是自己在年后决定看一下Jquery源码,并打算自己简单实现一下。那废话不多说,现在开始!
- 源码&案例已经上传至我的Github
为什么要使用jQuery
- 可通过任意(css选择器)来查询文档元素
- 简洁的语法,比原生JS更简便的操作选中的元素
开始实现之前需要明确
- 自己必须得会用Jquery,必须熟悉Jquery的方法使用,文档戳这里Jquery中文文档
- jQuery定义了一个全局函数,该函数使用频繁,那就给它改名为 () 的返回值是一个jQuery对象 , 这里要注意它与JavaScript直接获取 dom 是不同的; jQuery获取DOM只能用jQuery的方法来操作DOM,JavaScript同理,两者不能互相调用和使用披此的方法。
- 在jQuery类库中,最重要的方法是jQuery()方法 (也就是 $()) , 它的功能也是非常的强大的,下面给大家介绍集中在使用jQuery常用的调用方式
// 1. 传入css 选择器 $('在这里填入css选择器') // 2. 传入document,window $(document) // 3. 传入函数 $(function(){ // 需要执行的内容 }) // 其实$() 还支持 第二个参数,这里就不过多解释了,感兴趣的可以去看官方文档 - 简单实现jQuery调用方式,以及其他操作DOM的功能
// 首先创建一个构造函数 var jQuery = function(selector,context){ this.prevObject = context ? context:[document]; this.init(selector) } //初始化状态 分两种传参情况 jQuery.prototype.init=function(selector){ //1. css 选择器 if(typeof selector==='string'){ [...document.querySelectorAll(selector)].forEach((item,index)=>{ this[index]=item; }); //2. 传入函数 }else if(typeof selector==='function'){ document.addEventListener('DOMContentLoaded',selector); } //因为上面 $(document) 调用方法与$(funciton(){})执行效果一样,所以这里值实现后面的 }
上面的调用方法基本就实现了,那我们就简单实现一下其他的方法吧)
-
eq() 方法的实现
jQuery.prototype.eq=function(index){ index = index?index:0; return new jQuery(this[index],this); //将当前装,第一状态返回为了使用后end()方法 }, -
end() 方法的实现
//获取第一状态 jQuery.prototype.end=function(){ return this.prevObject; }, -
css() 方法的实现
jQuery.prototype.css=function(...style){ // style 传参需要考虑两种形式 第一种css("color","red") 第二种就是以对象的形式传递了 if(!this[0]){ return this; } if(typeof(style[0])!=='object'){ //通过属性Object.keys(this)索引改变样式 Object.keys(this).forEach((item,index)=>{ if(typeof (parseInt(item))=='number'&& !isNaN(parseInt(item))){ this.setStyle(this[item],style[0],style[1]); } }) }else{ Object.keys(this).forEach((item,index)=>{ if(typeof (parseInt(item))=='number'&& !isNaN(parseInt(item))){ for(let name in style[0]){ this.setStyle(this[item],name,style[0][name]) } } }) } return this; }, //setStyle 函数 来改变元素的样式 setStyle:function(ele,name,value){ ele.style[name]=value; }, -
removeClass() 方法的实现
// removeClass 方法的实现实现就简单很多了,包括 addclass,toggleClass 方法就不去实现了原理与removeClass类似 jQuery.prototype.removeClass=function(className){ Object.keys(this).forEach((item,index)=>{ if(typeof (parseInt(item))=='number'&& !isNaN(parseInt(item))){ this[item].classList.remove(className); } }) return new jQuery(this,this) }, -
on(事件名,回调函数)
jQuery.prototype.on=function(eventNames,fn){ //这里需要考虑eventNames 参数不一定是字符串 还可能是数组 let events = eventNames.split(" "); Object.keys(this).forEach((item,index)=>{ if(typeof (parseInt(item))=='number'&& !isNaN(parseInt(item))){ events.forEach(e=>this[item].addEventListener(e,fn)); } }) return this; } -
最后就Ajax了,让我们的看看Jquery的Ajax是如何封装的
//这里Ajax与Jquery的源码一样都是在创建实例之后加入Ajax方法的,其实我实现也很简单就是使用元素JavaScript封装Ajax之后添加到实例上就可以了; window.jQuery = window.$ = function(selector,context){ return new jQuery(selector,context); }; $.ajax=function(options){ var type,params,xhr; // 请求类型,传参,http实例 options = options || {}; type = (options.type||'GET').toUpperCase(), params = formsParams(options.data); // 创建实例 if(window.XMLHttpRequest){ xhr=new XMLHttpRequest(); }else if(window.ActiveObject){//兼容IE6以下版本 xhr=new ActiveXobject('Microsoft.XMLHTTP'); } //发送请求 GET/POST if(type=='GET'){ xhr.open("get",options.url + "?" + params,true); xhr.setRequestHeader(options.headers||"Content-Type", "application/json;charset=utf-8"); xhr.send(); }else if(type=="POST"){ xhr.open("post",options.url,true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(params); } // 可以自己拓展 put //设置超时时间 setTimeout(function(){ if(xhr.readySate!=4){ xhr.abort(); } },options.timeout||2000); xhr.onreadystatechange = function(){ if(xhr.readySate=4&&xhr.status==200){ options.success(xhr.responseText); }else{ options.error(xhr.status); } } }; // 格式化数据格式的 function formsParams(data){ var arr = []; for(let key in data){ arr.push(key+'='+data[key]) } return arr.join('&'); }
整体就实现这么多,感兴趣的朋友可以自己去看一下JQuery,并继续再此基础上完善。
- 下面使用我们刚刚封装的Jquery来做一个轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./JQE.js"></script> </head> <style> .dome{ width:300px; height: 200px; display: flex; flex-direction: row; background: red; } .dome .swiper{ flex: 1; position: relative; } .dome .swiper .imgs{ width: 100%; position: absolute; top: 0; left: 0; display: none; } .btn{ cursor: pointer; } </style> <body> <div class="dome"> <div class=" btn pre">《</div> <div class="swiper"> <img class="imgs" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/951ee8139e244bb1a7e3aa33fb7838e2~tplv-k3u1fbpfcp-zoom-1.image" alt=""> <img class="imgs" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4e267239cd1a48bc83cdf1c9d88dec49~tplv-k3u1fbpfcp-zoom-1.image" alt=""> <img class="imgs" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a0216e5f6bf04b5f9ba0ee0a81a7be06~tplv-k3u1fbpfcp-zoom-1.image" alt=""> </div> <div class=" btn next">》</div> </div> </body> <script> $(function(){ var num = 0; $('.pre').on('click',function(){ move(-1) }) $('.next').on('click',function(){ move(1) }) $('.imgs').eq(0).css("display","block"); function move(dot){ num+=1*dot; num = num>$('.imgs').length()-1?0:num; num = num<0?$('.imgs').length()-1:num; console.log(num) $('.imgs').eq(num).css("display","block").siblings('.imgs').css("display","none") } }) </script> </html> //是不是用jQuery写轮播图很简单啊
总结
个人认为JQuery主要使用的还是是链式操作,JS中10行代码能做的有可能在Jquery中只用1-2行就能解决,看过源码之后,自己也学到了不少东西,比如Jquery的链式操作,还有设计模式等等,强烈简易,前端进阶的朋友去挑战一下。不单单是学习,也是对自己JS能力的一种锻炼, 看到这里,关于本篇内容就到最后了,文章如有不足之处还请留言反馈,感谢支持。