虽然目前市面上jquery基本很少有公司使用(旧项目除外),
基本上都是在使用MVVM框架,而我本人也是使用vue比较频繁。
但是jquery里面实现的原理还是值得去学习和借鉴。
那么我现在来记录一下我所封装jquery的一个过程。
假设有以下的DOM节点,我先使用对象方法的形式来获取节点
<div id="box">box</div>
<p>段落1</p>
<p>段落2</p>
<p>段落3</p>
base.js
var Base = {
getId(id){ //获取元素id的方法
return document.getElementById(id)
},
getTagName(tag){ //获取元素标签的方法
return document.getElementsByTagName(tag)
}
}
通过Base.getId('box')和Base.getTagName('p')是可以获取到元素的节点的。
console.log(Base.getId("box")) //id为box的元素
console.log(Base.getTagName("p"))//获取p标签的元素
但这里会有问题,我们使用jq的时候,很多情况都是在使用它的连缀方法,
那么也就是说我们要想实现连缀,则必须方法调用完后,
都必须要返回这个对象的本身,方法才可以继续进行。
所以就要通过es5中的构造函数来实现。那么调用的方式也要发生一个改变。
var Base = new Base()
console.log(Base.getId("box")) //id为box的元素
console.log(Base.getTagName("p"))//获取p标签的元素
但这样还是没有办法实现一个连缀过程,
必须是要每次函数结束都要返回对象的本身,才可以实现连缀,那么就继续改造。
function Base(){
this.elements = []
this.getId = function(id){
this.elements.push(document.getElementById(id))
return this //返回对象本身方可实现连缀
}
this.getTagName = function(tag){
this.elements.push(document.getElementsByTagName(tag))
return this
}
}
调用方式
var Base = new Base()
console.log(Base.getId('box').elements[0]) //id为box的元素
console.log(Base.getTagName('p').elements) //获取p标签的集合
那么现在每次调用getId和getTagName,都会返回Base对象,
那么我们可以通过原型链的方式给构造函数Base()添加一些方法
function Base(){
this.elements = []
this.getId = function(id){
this.elements.push(document.getElementById(id))
return this //返回对象本身方可实现连缀
}
this.getTagName = function(tag){
var tags = document.getElementsByTagName(tag)
for(var i=0;i<tags.length;i++){
this.elements.push(tags[i]) //把每一个tag元素都放进this.elements数组中
}
return this
}
}
Base.prototype.css = function(attr,value){
for(var i=0;i<this.elements.length;i++){
this.elements[i].style[attr] = value
}
return this
}
在以上代码中,因为我们需要对每一个p标签都添加css样式,所以则必须使用for循环,遍历每一个元素。
Base.getTagName('p').css("color","red")
但这里会存在getId和getTagName共用一个对象的问题,
所以我们则必须每次都要实例化一个新的对象,所以以下是完整代码。
var $ = function(){
return new Base()
}
function Base(){
this.elements = []
this.getId = function(id){
this.elements.push(document.getElementById(id))
return this //返回对象本身方可实现连缀
}
this.getTagName = function(tag){
var tags = document.getElementsByTagName(tag)
for(var i=0;i<tags.length;i++){
this.elements.push(tags[i]) //把每一个tag元素都放进this.elements数组中
}
return this
}
}
Base.prototype.css = function(attr,value){
for(var i=0;i<this.elements.length;i++){
this.elements[i].style[attr] = value
}
return this
}
Base.prototype.html = function(str){
if(!str){
var pattern = /^(\s+)|(\s+)$/g //去除两端空白
return this.elements[0].innerHTML.replace(pattern,"")
}
for(var i=0;i<this.elements.length;i++){
this.elements[i].style[attr] = value
}
return this
}
Base.prototype.click = function(fn){
if(!fn){
console.warn('waring fn is undefine')
}
for(var i=0;i<this.elements.length;i++){
this.elements[i].onclick = fn
}
return this
}
调用
$().getTagName('p').css("color","red")
$().getId('box').css("color","green")