jQuery实质为构造函数,这个构造函数接受一个参数,jQuery内部通过这个参数利用原生的API找到相对应的DOM节点,然后把节点挂载到实例的jQuery对象上,给这个构造函数的原型上添加了许多方法,方法实例对象JQuery对象调用.
1.模拟实现简易的jQuery
我们可以通过自执行函数,在函数内部创建一个jQuery对象,这个对象接受一个参数为,返回一个实例化的jquer对象
jQuery是一个典型的工厂模式,你给它一个什么参数,它返回给你符合参数要求的DOM元素.
jQuery,内部帮我们调用了new, 让我们调用更加方便.
1.1 搭建基本结构
(function (){
let jQuery = function(selector){
// 内部手动调用new, 返回实例对象
return new jQuery.fn.init(selector)// new一下init, init 才是真正的构造函数
}
//jQuery.prototype的简写方式
jQuery.fn = jQuery.prototype;
jQuery.fn.init = function(selector){ }//这里面实现真正的构造函数
//让init和jQuery的原型指向同一个对象, 便于挂载实例方法
jQuery.fn.init.prototype = jQuery.fn;
//最后把jQuery挂载到window上. 方便调用
window.$ = window.jQuery = jQuery
})()
1.2 实现构造函数
jQuery.fn.init = function (selector) {
//我们对用户传入的参数进行判断, 如果传入的参数包含,就通过类名获取DOM元素
if(selector.tagName){// 如果传入的参是一个原生的DOM元素, 那么它对应的标签名一定有值
this[0] = selector;
this.length = 1;
return //此时应该打断函数执行, 避免发生错误
}
if (selector.includes(".")) {
let name = selector.slice(1);//截取类名
// 原生的HTMLcollection集合,不方便我们循环, 我们通过Array.from把他转为数组
let DOMList = Array.from(document.getElementsByClassName(name));
//遍历这个DOM列表, 给实例化的jQuery对象通过键值对添加相应的DOM元素
for (let [key, item] of DOMList.entries()) {
this[key] = item;
}
//给实例化对象添加一个length属性, 记录DOM元素的个数
this.length = DOMList.length
}
}
在控制台输入console.log($(".item")), 打印成功,说明构造函数没问题.
image-20200601121939822.png
1.3 封装获取实例化对象DOM元素函数
获取实例化对象的所有DOM元素,方便我们将来给构造函数的原型挂载方法时,调用需要的DOM元素.
//封装获取原生dom对象数组的函数
function getDom(obj){
let DOMlist = [],
length = obj.length;//获取length属性 控制循环的次数
for(let i = 0; i < length; i++){
DOMlist.push(obj[i])//往要返回的数组添加节点
}
//返回DOM节点列表
return DOMlist
}
1.4 click方法
我们模拟一下jQuery的click方法,
首先我们接受一个回调函数,重点我们要把将回调函数的内部this绑定到相对应的DOM节点.
//给构造函数原型添加click方法 这个方法接受一个回调函数
jQuery.fn.click = function(callback){
//判断一下传入的参数类型是否为函数 如果不是就抛出一个错误
if(typeof callback !== "function"){
throw new Error("The argument should be a function");
return
}
//获取DOM元素列表
let DOMList = getDom(this);
//然后我们用原生的事件监听给每个DOM元素绑定点击事件
for(let [key,item] of DOMList.entries()){
item.addEventListener("click",function(ev){
//接着我们通过call将回调函数的内部this指向相对应的this节点,传入一个ev事件对象
callback.call(this,ev)
})
}
//返回实例对象,方便我们链式调用
return this
}
}
1.5 css方法
我们这里简单模拟一下设置单个css属性值, 首先这个方法一个接受两个参数,第一个参数为属性值名 第二个为属性值
jQuery.fn.css = function(name,value){
//判断一下参数类型是否正确
if(typeof name !== "string" && value !== "object" ){
throw new Error("The argument should be a string ")
return
}
//获取DOM列表
let DOMList = getDom(this);
//循环设置css属性值
DOMList.forEach((item)=>{
item.style.cssText = `${name}:${value}`
})
return this
}
1.6 each方法
回调函数接受两个参数,第一个为下标, 第二个为对应的DOM元素,
jQuery.fn.each = function(fn){
let result = getDom(this);
for(let [key,val] of result.entries()){
fn.call(null,key,val)//如果call 给回调函数传入index和item
}
return this
}
1.7 简单的测试案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="item">按钮1</button>
<button class="item">按钮2</button>
<button class="item">按钮3</button>
<button class="item">按钮4</button>
<button class="item">按钮5</button>
</body>
</script>
<!-- 引入我们写好的js文件 -->
<script src="./jquey.js"></script>
<script>
//给所有的按钮绑定点击事件,每次只给当前点击的元素添加颜色
$(".item").click(function (ev) {
$(".item").each((index, item) => {
$(item).css("color", "")//清空之前设置的字体颜色
});
$(this).css("color", "red")//给当前点击的元素添加字体颜色
});
</script>
</html>
ok到这里就差不多,这里实现的都是一些很基本的功能, 可能不是很完美.但可以拿来娱乐娱乐.我觉得学习不仅要知其然, 也要知其所以然.我们不仅会用轮子,也要了解一点怎么造轮子.这样我们的个人水平可以更进一步,将来选择的权利就会更多.
.
网友评论