在我们日常学习编程中,为了效率以及公司盈利,我们常常会用到各种各样的库或者框架,本着来说,不管是库还是框架,都一样,就是把原生的知识,封装起来,让我在写下很少的代码就可以达到我们想要的效果,而jQ,作为一个库,为什么那么多人愿意去用。
有几点必须要明白,
第一,jQ没有像那些框架一样,只需要改变数据,就可以影响到dom,我们还是需要自己扎实的基本功去完成我们的项目,这就意味着 jQ非常适合学习,让我们的基础更好,我们还是需要像操作原生dom一样去写代码,只不过让难受的原生JS变得更好用而已
第二,虽说jQ相对现在的流行框架来说,已经算是很过时了,但是如果对于一个基础很好,书写代码的速度也是可以达到那些框架一样的速度,并且很多时候框架的报错并不准确,一旦遇到框架报不出的错误,但代码本身有BUG时,是非常麻烦的。但是jQ不会。
第三,用户体系非常庞大,很多人已经习惯了jQ的API了,并且当基础好时,框架也只是简简单单的看看文档就直接用了。
说了这么多开始写封装,最常见的API :addClass() 、removeClass()、css()、text(),基本都类似;
简单来说jQ的含义是一个函数,接受一个选择器或者节点返回一个对象,对象中有非常多的方法,那我们来定义一个函数:
var jQ = function (node) { }
首先我们需要对传入的节点进行筛选,看属于class还是id等,这里我就不写了,全部都用id来。
那我只需要获取到传入id对应的DOM元素即可。
var jQ = function (node) {
var id = document.getElementById(node)
}
然后我们在调用这个函数时应该暴露非常多的方法,所以我们需要这个函数的返回值是一个对象,对象中包含了大量的方法,
var jQ = function (node) {
var id = document.getElementById(node)
return {
....
}
}
这样我们就达到了目的,然后我们开始部署我们的代码:
var jQ = function (node) {
var id = document.getElementById(node)
return {
addClass() {
arguments[0] ? id.classList.add(arguments[0]): console.error('class is null')
},
}
}
做一个判断,确保传入class,否则就报错。
接下来的方法都是如此:
var jQ= function (node) {
var id = document.getElementById(node)
return {
addClass() {
arguments[0] ? id.classList.add(arguments[0]): console.error('class is null')
},
text() {
arguments[0] ? id.innerText = arguments[0] : console.log(id.innerText)
},
removeClass() {
arguments[0] ? id.classList.remove(arguments[0]) : console.error('this class is not defined')
},
css() {
if(arguments[0] instanceof Object) {
let obj = JSON.stringify (arguments[0])
let str = obj.slice(1,obj.length-1)
let style = str.split(',').join(';')
let string = style.replace(/"([^"]*)"/g, "$1")
console.log(string)
id.style.cssText = string
}
}
}
}
虽然感觉还行已经变得有点像jQ了,但是,jQ最著名的还是链式操作,我们这个并没有体现出,怎么办呢? 这里还记得new关键字吗?我们可以把所有得方法都写在new 返回得对象的原型上面,而这个对象只存入我们传入的id,当我们每次调用方法时都把这个对象再返回出去(因为带有id),这个对象叫作this,看代码:
var jQ= function (node) {
return new JQuery(node)
}
function JQuery(node) {
this.id = document.getElementById(node)
}
JQuery.prototype.addClass = function () {
arguments[0] ? this.id.classList.add(arguments[0]) : console.error('class is null')
return this
}
JQuery.prototype.text = function () {
arguments[0] ? this.id.innerText = arguments[0] : console.log(this.id.innerText)
return this
}
JQuery.prototype.removeClass = function () {
arguments[0] ? this.id.classList.remove(arguments[0]) : console.error('this class is not defined')
return this
}
JQuery.prototype.css = function () {
if (arguments[0] instanceof Object) {
let obj = JSON.stringify(arguments[0])
let str = obj.slice(1, obj.length - 1)
let style = str.split(',').join(';')
let string = style.replace(/"([^"]*)"/g, "$1")
this.id.style.cssText = string
}
return this
}
下面我来试试这串代码
<ul>
<li id="item1">hah</li>
<li id="item2">hah</li>
<li id="item3">hah</li>
<li id="item4">hah</li>
<li id="item5">hah</li>
</ul>
创建DOM元素来测试,传值:
jQ('item3').addClass('active').text('haha').css({
background: 'red',
color: 'white'
})
OK没有问题,这里比较重点得就是this指的什么,this一定要看函数调用,谁调用指向谁,比如:
fn() 这个就是window
obj.fn() 这个就是obj
fn.call(obj) 这个也是obj
fn.apply(obj) 这个还是obj
还有bind呀等 绑定谁是this,谁就是this,
箭头函数没有this,this会指向它的父作用域。