jQuery的设计原理
在前端开发的技术圈中,jQuery可谓是无人不知无人不晓了,因为其简单容易上手的语法和API,很多人可以看文档直接上手就写。
但是有没有想过,jQuery到底是怎么实现的呢?
说到底,jQuery很多时候还是在操作DOM,但是为何不直接使用原生的js呢?原因很简单,因为不好用。
下面举个例子说明。
用原生js实现类似jQuery的方法,给元素添加一个类(class)、获取或赋值内容。
1.获取元素
要给元素添加class或者添加内容,首先是要能够获取到元素本身。
//公用HTML内容
...
<head>
...
<style>
.red{color:red;}
</style>
</head>
<body>
<div>我是内容1</div>
<div>我是内容2</div>
<div>我是内容3</div>
<div>我是内容4</div>
</body>
...
//js内容
window.jQuery = function(nodeOrSelector){
let nodes = {} //声明一个空对象
if(typeof nodeOrSelector === 'string'){ //判断传输的参数是否是字符串,如果是,则执行下面代码
let temp = document.querySelectorAll(nodeOrSelector) //用一个变量 temp ,把获取到的伪数组,放入当中
for(let i =0; i<temp.length;i++){ //遍历这个伪数组
nodes[i]=temp[i] //把伪数组的内容,添加到nodes对象当中
}
nodes.length=temp.length //把伪数组的length属性,也添加到nodes对象当中
}
else if(nodeOrSelector instanceof Node){ //如果传输的参数是一个节点,则执行下面代码
nodes = { //如果是一个节点,也把参数节点放入到一个伪数组当中
0:nodeOrSelector,
length:1
}
}
//第一部分
return nodes //把对象nodes作为返回值
}
至此,就可以使用函数jQuery(),通过传入参数,把获取到的节点或者选择器放入到对象nodes当中。
例如,获取页面中的div
var div = jQuery('div')
console.log(div) // 打印出 {0: div, 1: div, 2: div, 3: div, length: 4}
打印出一个对象 {0: div, 1: div, 2: div, 3: div, length: 4} 把页面中的四个div存入对象中。
2.操作元素
把获取到的元素放进nodes对象以后,就可以像操作对象一样,给对象添加属性和值。
例如在jQuery函数中,添加nodes属性,属性值为一个函数。
2-1.元素添加类
// 在第一部分和return nodes行间,添加nodes的属性
nodes.addClass =function(classes){ //nodes对象添加一个addClass属性,属性值为一个函数
for(let i=0;i<nodes.length;i++){ //遍历nodes的对象内容,获取到元素
nodes[i].classList.add(classes) //给第i个属性,添加一个类,类名为函数传进的参数
}
}
至此,可以使用addClass()给元素添加一个类(class)
var div = jQuery('div')
div.addClass('red')
运行上面的代码,就可以给每一个div添加一个类(class="red")
2-2.获取或更改元素内容
//在addClass行后添加
nodes.setText = function(text){ //nodes对象添加一个setText属性,属性值为一个函数
if(text === undefined){ //判断函数传入的参数,是否为undefined,即元素内容为空,如果是,执行下面代码
var texts=[] //声明一个空数组
for(let i =0; i<nodes.length;i++){ //遍历 nodes对象,
texts.push(nodes[i].textContent) //给texts添加value值,值为nodes遍历的内容
}
return texts //把texts数组作为返回值
else{ //如果传入的参数,不等于undefined,即元素内有内容,则执行下面代码
for(let i=0;i<nodes.length;i++){ //遍历nodes对象
nodes[i].textContent = text //把参数text当做内容,替换掉原来的内容
}
}
}
至此,可以使用setText(), 获取或者更改元素的内容
当直接使用setText(), 不传参数,则为获取内容到一个数组中。
当使用setText(xxx), 传一个参数时,则为把参数作为内容,替换掉原来的内容。
console.log(div.setText()) //打印出数组["我是内容1", "我是内容2", "我是内容3", "我是内容4"]
div.setText('hi') //更换div的内容为hi
至此,类似jQuery的方法,已经实现。
但是,我们发现,使用的方式,还是和jQuery有所差异。jQuery比这个方便多了。
下面在进行一个完善,完善调用函数部分。
window.$ = jQuery
$('div').addClass('red')
$('div').setText('hi')
这就和jQuery调用API没有什么差异了。
3.完整代码
window.jQuery = function(nodeOrSelector){
//获取到元素
let nodes = {}
if(typeof nodeOrSelector === 'string'){
let temp = document.querySelectorAll(nodeOrSelector)
for(let i =0; i<temp.length;i++){
nodes[i]=temp[i]
}
nodes.length=temp.length
}
else if(nodeOrSelector instanceof Node){
nodes = {
0:nodeOrSelector,
length:1
}
}
//addClass
nodes.addClass = function(classes){
for(let i=0;i<nodes.length;i++){
nodes[i].classList.add(classes)
}
}
//setText
nodes.setText = function(text){
if(text === undefined){
var texts=[]
for(let i =0; i<nodes.length;i++){
texts.push(nodes[i].textContent)
}
return texts
}
else{
for(let i=0;i<nodes.length;i++){
nodes[i].textContent = text
}
}
}
return nodes
}
//调用函数
window.$ = jQuery
$('div').addClass('red')
$('div').setText('hi')
上述的内荣,是jQuery 的设计思想,并不是 jQuery 的实际实现方式。这里只是模拟实现jQuery。