jQuery简介
jQuery是一个优秀的javascript代码库(JS库)。顾名思义:j → js,Query → 查询;
所以可知jQuery主要是用来做查询的,即获取文档元素进行操作。
jQuery副标题是:write less,do more.
所以可知使用jQuery可以简化原生DOM编程;
jQuery特点:
- 经典:jQuery里包含了很多经典的设计思想,值得学习;
- 流行: jQuery是目前前端最长寿的库,也是世界上使用范围最广的库;
- 好用:封装了常用的代码,提供简洁的设计模式,上手快,用起来爽;
- 兼容:jQuery帮助开发者解决了很多浏览器兼容问题
浅析jQuery设计思想
先上代码:
// 先提供一个全局函数:
window.jQuery = function(){}
// 实现一个简单的API:
// 目标效果:element.addClass('red')能给元素添加类
window.jQuery = function(selector){
// 接受一个选择器,用来获取元素
const elements = document.querySelectorAll(selector)
const api = {
addClass(className){
// 因为获取到的可能不止一个元素,而是多个元素组成的伪数组
// 所以要遍历
for(let i = 0;i < elements.length;i++){
elements[i].classList.add(className)
}
return api
}
}
return api
}
思路分析:
jQuery是一个函数,接受一个CSS选择器,给它这个选择器,它就能获取到这些元素。但是jQuery不会去返回这些元素,而是返回一些对象。
这些对象里面的内容是一个方法,也就是一个函数,这些函数可以去操作刚刚获取到的这些元素:比如改变元素的样式,修改元素里的文本内容等。
结构示意:
window.jQuery(选择器){
元素(们) = document.querySelectorAll(选择器)
对象 = {
方法1:函数(){操作获取到的元素},
方法2:函数(){操作获取到的元素},
...
}
return 对象
}
上面的代码中,对象里方法访问了外部的元素,也就是访问了外部的变量,所以这里用到了闭包;
因为对象里的方法操作了元素,然后返回的还是本来这个对象,所以可以继续调用对象里的方法:
html:
<div id="test">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>
jQuery('.child').addClass('red').addClass('blue').addClass('green')
// jQuery获取到所有类名是child的元素,然后用对象的方法来操作元素,操作完又返回对象,又可以接着把方法给"点"出来
// 这就是jQuery的链式风格
// 这样看可能更直观
jQuery('.child').addClass('red')
.addClass('blue')
.addClass('green')
// 换个方式理解:
obj.fn(p1)
// 对象obj调用一个函数fn,p1为函数的接受参数
// 你在调用fn这个函数的时候,肯定是通过obj对象来调用的,类似于上面的addClass,是通过api对象调用的
// 所以这里把前面调用的对象当做this,用call的形式体现出来就是:
obj.fn,call(obj,p1)
// 那么可想而知:如果调用完函数,return这个前面这个对象,那不就可以继续调用对象里的方法了吗?
// 这就相当于把这个对象从前面传到了后面,传到后面后又能接着调用函数,这就是链式操作
结合上面的思考,把代码改写一下:
window.jQuery = function(selector){
const elements = document.querySelectorAll(selector)
return {
addClass(className){
for(let i = 0;i < elements.length;i++){
elements[i].classList.add(className)
}
return this // 函数用对象来调用,那么函数的this就是指向前面这个对象,所以直接改成返回this
}
}
}
这里注意不要因为多个return把结构搞混:
第一个 return 是下面的 return api 修改而来的,属于 jQuery 这个函数的返回值;
第二个 return 是对象里的 addClass 方法的返回值;
jQuery是构造函数吗
是:jQuery函数确实构造出来了一个对象;
不是:正常的构造函数去构造一个实例对象需要用到 new 关键字,但是jQuery却没有;
// 比如:
let object = new Object()
Object是个构造函数
对象object是构造函数Object构造出来的对象
let array = new Array()
Array是个构造函数
对象array是构造函数Array构造出来的对象
let function = new Function()
Function是个构造函数
函数对象function是构造函数Function构造出来的对象
总结:
jQuery是构造函数,但不是严格意义上的构造函数。说它是构造函数,是因为它确实构造出了一个对象。说它不是严格意义的上的构造函数,是因为它在构造对象时不用加 new;
$
为了追求更简洁更方便的写法,jQuery作者给jQuery加了一个别名:$
window.jQuery = function(){...}
// 写完jQuery代码后:
window.$ = window.jQuery
// 要放在jQuery后面,而不是前面
// 更简洁的写法:
window.$ = window.jQuery = function(){...}
jQuery命名风格
DOM对象使用DOM的API,比如:querySelector、appendChild...
jQuery对象使用jQuery的API,比如:find、has...
假如遇到这样的代码,就容易让人产生误解:
const div = $('div#test')
乍得一看会以为div是DOM对象,但是实际上div是jQuery构造的对象,如何避免这种情况呢?
为了避免这种情况,所以需要一个约定:
代码中所有jQuery对象,以$命名开头
const div = document.querySelector('.test') // DOM对象
const $div = $('div#test') // jQuery对象
// $div.appendChild不存在,因为它不是DOM对象
// $div.find存在,因为它是jQuery对象
这样可以迅速的确定的一个对象是DOM对象还是jQuery对象,比较方便;
jQuery使用方法
jQuery的基本思想和主要用法,就是选择某个网页元素,然后对其进行操作;
获取网页元素
要获取、选择网页里的元素,需要将一个选择表达式,放进构造函数jQuery( )里,即$( ),这里的表达式可以是CSS选择器:
// 选择整个文档对象
$(document)
// 选择ID为myId的网页元素
$('.myId')
// 选择class为myClass的div元素
$('div.myClass')
// 选择name属性是first的input元素
$('input[name=first]')
上面都是我们熟悉的CSS选择器,另外jQuery还有一些特有的表达式:
// 选择网页中第一个a元素
$('a:first')
// 选择表格的奇数行
$('tr:odd')
// 选择id为myForm的表单里的input元素
$('#myForm:input')
// 选择可见的div元素
$('div:visible')
// 选择所有的div元素,除了前三个
$('div:gt(2)')
// gt:greater than 大于
// 选择当前处于动画状态的div元素
$('div:animated')
改变获取到的结果集
jQuery提供了很多强大的过滤器,可以对获取到的结果进行筛选,缩小选择的范围:
// 选择包含p元素的div元素
$('div').has('p')
// 选择类名class等于myClass的div元素
$('div').filter('.myClass')
// 选择类名class不等于myClass的div元素
$('div').not('myClass')
// 选择第一个div元素
$('div').first()
// 选择第六个div元素
$('div').eq(5)
// eq:equal 等于
从获取到的结果集合开始,移动到附近的相关元素:
// 选择div元素后面的第一个p元素
$('div').next('p')
// 选择div元素的父元素
$('div').parent()
// 选择离div最近的form父元素
$('div').closest('form')
// 选择div元素的所有子元素
$('div').children()
// 选择div元素的同级元素,也就是兄弟姐妹元素
$('div').siblings()
链式操作
原生DOM编程里,获取一个元素,然后对它进行一系列的操作:
// html:
<div id='test'></div>
// js:
let x = document.querySelector('#test');
x.innerText = 'hi';
x.style.background = 'red';
x.style.color = 'blue'
每一次操作都要单独写一行,不够方便。在jQuery里,选中网页元素后,可以对元素进行一系列的操作,并且所有操作都可以连在一起,以链条的形式写出来:
// 用jQuery改写上面的代码:
$('#test').text('hi').css({"background":"red","color":"blue"})
这样就比较简洁方便了,分解链条看看:
$('div').find('h3').eq(2).html('hello')
// 分解:
$('div') // 找到div元素
.find('h3') // 获取div元素里的h3元素
.eq(2) // 获取第三个h3元素
.html('hello') // 把它的html内容改为hello
这就是jQuery的链式操作,每一步的jQuery操作,返回的都是jQuery对象,所以不同的操作可以连接在一起。
jQuery还提供了.end()方法,让结果可以后退一步:
$('div')
.find('h3')
.eq(2)
.html('hello')
.end() // 退回到选中的所有h3元素那一步
.eq(0) // 选择第一个h3元素
.html('World') // 把获取到的第一个h3元素内容改为World
元素操作:取值和赋值
操作网页元素,比较常见的需求就是取得元素的值,或者对它们进行赋值。
jQuery设计思想之四:使用同一个函数,来完成取值和赋值,也就是取值器和赋值器合一,(getter和setter),至于到底是取值还是赋值,由函数的参数来决定:
$('h1').html() // html()括号里没参数,那么就表示取出h1的值
$('h1').html('hi') // html()括号里有参数'hi',那么就表示对h1进行赋值
常见的取值和赋值函数:
// 取出或设置html内容
.html()
// 取出或设置text内容
.text()
// 取出或设置某个属性的值
.attr()
// 取出或设置某个元素的宽度
.width()
// 取出或设置某个元素的高度
.height()
// 取出或设置某个表单元素的值
.val()
注意:如果获取到的结果集合包含多个元素,那么赋值时,会对所有元素进行赋值;取值时,只会取第一个元素值。不过.text()是个特例,它会获取到所有元素的text内容。
元素操作:移动
jQuery设计思想之五:提供两组方法,来操作元素在网页中的位置移动。一组方法是直接移动元素,另一组方法是移动其他元素,达到移动原本想要移动位置的元素的目的。
// 假如我们选中一个div元素,需要把它移动到p元素后面:
// 方法1:用insertAfter()把div元素移动到p元素后面
$('div').insertAfter($('p'))
// 方法2:用after()把p元素加到div元素前面
$('p').after($('div'))
这两种方法表面上看,达到的效果是一样的,唯一的不同只是主体不同,视角不同。
但是实际上两个方法有一个重大的差别,就是返回的元素是不同的:
第一种方法返回的是div元素,第二种方法返回的是p元素,我们可以根据需要来选择相应的方法。
同模式的操作方法:
// 在获取的元素后面插入元素
insertAfter()和after()
// 在获取的元素前面插入元素
insertBefore()和before()
// 在获取的元素内部,从后面插入元素
appendTo()和append()
// 在获取的元素内部,从前面插入元素
prependTo()和prepend()
元素操作:复制、删除和创建
// 复制元素
clone()
// 删除元素
remove() 和 detach
// 两者区别:前者不保留被删除的元素,后者保留,以便重新插入文档来使用
// 清空元素内容,但是不删除元素
empty()
// 创建新元素:把新元素传入jQuery构造函数就行
$('<p>Hi</p>')
$('ul').append($('<li class="new">new list item</li>'))
工具方法
jQuery设计思想之六:除了对选择元素进行操作以外,还提供了一些与元素无关的工具方法(utility),不用选中元素也可以直接使用,就像JS的原生函数一样,可以直接用。
工具方法的实质:其实这里是用到了JS的继承原理,工具方法是jQuery构造函数上的方法,即jQuery.method(),所以可以直接使用。而那些操作元素的方法,则是定义在构造函数的prototype对象上的方法,即jQuery.prototype.method(),所以必须要生成实例才能使用。
常见工具方法:
// 去除字符串两端的空格
$.trim()
// 遍历一个数组或者对象
$.each()
// 返回一个值在数组中的索引位置,如果改值不在这个数组里,就返回-1
$.inArray()
// 返回数组中符合某个标准的元素
$.grep()
// 把多个对象合并成一个对象
$.extend()
// 把对象转换成数组
$.makeArray()
// 判断对象的类别(函数对象、日期对象、数组对象、正则对象等)
$.type
// 判断某个参数是不是数组
$.isArray()
// 判断某个对象是否为空(也就是对象不含有任何属性)
$.isEmptyObject()
// 判断某个对象是否为函数
$.isFunction()
// 判断参数是否为用 { } 或者 new Object 建立的对象
$.isPlainObject()
// 判断浏览器是否支持某个特性
$.support()
事件操作
jQuery设计思想之七:把事件直接绑定在网页元素上;
示例:
$('p').click(function(){
alert('hi')
});
jQuery支持事件:
// 表单元素获得焦点
.focus()
// 表单元素失去焦点
.blur()
// 表单元素的值发生变化
.change()
// 子元素获得焦点
.focusin()
// 子元素失去焦点
.focusout()
// 鼠标单击
.click()
// 鼠标双击
.dbclick()
// 同时为mouseenter和mouseleave事件指定处理函数
.hover()
// 按下键盘,长时间按键只返回一个事件
.keydown()
// 按下键盘,长时间按键会返回多个事件
.keypress()
// 松开键盘
.keyup()
// 元素加载完毕
.load()
// 按下鼠标
.mousedown()
// 松开鼠标
.mouseup()
// 鼠标进入(进入子元素不会触发)
.mouseenter()
// 鼠标离开(离开子元素不会触发)
.mouseleave()
// 鼠标进入(进入子元素也会触发)
.mouseover()
// 鼠标离开(离开子元素也会触发)
.mouseout()
// 鼠标在元素内部移动
.mousemove()
// DOM加载完成
.ready()
// 浏览器窗口的大小发生改变
.resize()
// 滚动条位置发生变化
.scroll()
// 用户选中文本框的内容
.select()
// 用户提交表单
.submit()
// 根据鼠标点击的次数,依次运行多个函数
.toggle
// 用户离开界面
.unload()
bind
上面的事件都在jQuery内部,都是.bind()的方便的用法,使用.bind()可以更灵活的控制事件,比如多个事件绑定同一个函数:
$('input').bind(
'click change',//同时绑定click和change事件
function(){
alert('hello');
}
)
unbind
使用unbind解除事件绑定:
$('p').unbind('click');
one
如果只想让事件运行一次,可以使用.one()方法:
$('p').one('click',function(){
alert('hi') //这个事件只会运行一次,之后再点击就不会运行了
})
事件对象
所有事件处理函数,都可以接受一个事件对象(event object)作为参数,比如下面的e:
$('p').click(function(e){
console.log(e.type); // "click"
})
这个事件对象有一些属性和方法:
// 事件发生时,鼠标距离网页左上角的水平距离
event.pageX
// 事件发生时,鼠标距离网页左上角的垂直距离
event.pageY
// 事件的类型(比如:click)
event.type
// 按下了哪个键
event.which
// 在事件对象上绑定数据,然后传入事件处理函数
event.data
// 事件针对的网页元素
event.target
// 阻止事件的默认行为(比如点击链接,会自动打开新页面)
event.preventDefault()
// 停止事件向上层元素冒泡
event.stopPropagation()
在事件处理函数中,可以用this关键字,返回事件针对的DOM元素:
$('a').click(function(e){
if($(this).attr('href').match('evil')){ // 如果认为是有害链接
e.preventDefault(); // 阻止打开
$(this).addClass('evil'); // 并且加上一个类名,表示链接有害
}
})
自动触发一个事件:
// 两种方法自动触发事件
// 先定义好事件:
$('a').click(function(){
alert('clicked!')
})
// 第一种:直接使用事件函数
$('a').click();
// 第二种:用.trigger()或.triggerHandler()
$('a').trigger('click');
特殊效果
jQuery允许对象呈现一些特殊的效果;
// 隐藏一个元素
.hide()
// 显示元素
.show()
// 淡入
.fadeIn()
// 淡出
.fadeOut()
// 调整透明度
.fadeTo()
// 向下展开
.slideFDown()
// 向上卷起
.slideUp()
// 依次展开或卷起某个元素
.slideToggle()
// 依次展示或隐藏某个元素
.toggle()
注意:除了.show()和.hide(),其他所有特效的默认执行时间都是400毫秒(ms),我们可以手动改变这个时间:
$('p').fadeIn(300) // 300毫秒内淡入
$('p').fadeOut('slow') // 缓慢的淡出
特效结束以后,还可以指定执行一个函数:
$('p').fadeIn(300,function(){
$(this).remove();
})
想要一些更复杂的特效,可以自己用.animate()来定义:
$('div').animate({
{
left:'+=50', // 不断往右移
opacity: 0.25 // 指定透明度
},
300, // 执行时间
function(){
alert('done!') // 回调函数
}
})
可以用.stop()和.delay()来停止或延缓特效的执行;
关闭所有网页特效:把$.fx.off的值设置为true即可;
推荐博客:jQuery设计思想-阮一峰