前言
在如今的前端框架潮流中,毫无疑问React,Vue已经走在了第一线,越来越多前端开发者加入其中,但是昔日的霸主jQuery依然不可小视,在过去一年的调研中 jQuery依然位列前茅,加之最近在维护老的项目,因此再次阅读《锋利的jQuery》,希望有更多的理解。
优势
优势实在是太多了,个人觉得其中的:选择器,DOM操作封装,链式操作等真的是非常优秀;
安装
通过script标签直接引入jQuery文件即可正常使用
jQuery对象和DOM对象
先说结论,jQuery对象是jQuery对DOM对象进行了一次的封装,以供在jQuery中使用,这两个某种程度上说不是一回事;
DOM对象:文档对象模型,可以这么理解,这是浏览器提供的原生对象,JS能直接进行操作的是DOM对象,比如通过document.getELementById(‘my’)这个方法,找到了页面上的一个id名为my的元素;
jQuery对象:jQuery将DOM对象进行了一次包装后产生的对象,为什么要包装,因为包装后的DOM对象(也就是jQuery对象)可以使用jQuery里的方法,这些方法极大的简化了JS的书写规则,比如:
//jQuery中,这样便已经选择了id名为my的元素节点
$('#my')
//js中,需要这样才是选择了id名为my的元素节点
document.getELementById('my')
jQuery对象因为和DOM对象某种程度上说不是一回事,因此这两个里面的方法是不能相互使用的,比如:
//获取id为my的元素的文档内容
$('#my').html();
//下面这种使用是错误的,html()这个方法是jQuery提供的,
//因此能使用html()这个方法的对象必须是jQuery对象
document.getELementById('my').html()
//在DOM对象中获取相同的内容,比如使用DOM提供的方法
document.getELementById('my').innerHTML
DOM对象转成jQuery对象:将DOM对象转成jQuery对象只需要使用(document.getELementById(‘my’));
jQuery对象转成DOM对象:在jQuery对象的实现中,是将获取到的所有元素节点放在了一个类数组中,因此可以通过下标的方式获取到DOM对象,比如:
$('.my')
//获取到页面上所有class中带有my的元素节点,此时所有的元素节点是存放在一个类数组中的
//因此,假如需要获取的是第一个class中带有my的元素节点,可以通过$('.my')[0]获取到
选择器
毫无疑问,在我个人心中,jQuery中的选择器功能绝对是在所有功能排行中数一数二的...没办法,实在太好用了,它完全继承了CSS选择器的风格,可以快速,便捷的找出特地的DOM元素,进行处理,并且到遇到错误时,避免浏览器报错而阻塞了进程;
基本选择器
选择器 | 描述 | 返回 | 示例 |
#id | 匹配一个指定id的元素 | 单个元素 | $(’#my’),获取id名为my的元素 |
.class | 匹配所有类名中包含class的元素 | 元素的集合 | $(’.test’),获取所有类名中包含test的元素 |
element | 匹配所有指定元素名的元素 | 元素的集合 | $(‘p’),获取的是所有的p元素 |
* | 匹配页面上所有元素 | 元素的集合 | $(’*’),获取页面上所有的元素 |
el1,el2,el3 | 将所有选择器匹配到后一起返回 | 元素的集合 | $(‘div,.test,#my’),将所有div,类名中有test,id为my的元素一起获取到返回 |
层次选择器
选择器 | 描述 | 返回 | 示例 |
$(‘el div’) | 匹配el元素里面的所有div元素(包括子元素,孙元素等等所有后代) | 元素的集合 | $(’#my div’),获取id名为my的元素里面的所有div元素 |
$(‘el>div’) | 匹配el的子元素里所有的div元素(只有子元素,不包含孙元素等待) | 元素的集合 | $(’#my>div’),获取id名为my的子元素里的所有的div元素 |
$(‘el+div’) | 匹配紧跟着el元素的div元素 | 元素的集合 | $(‘p+div’),获取的是所有紧跟着p元素的div元素 |
$(‘el~div’) | 匹配el元素之后的所有兄弟元素 | 元素的集合 | $(‘p+div’),获取的是所有p元素后面的div元素 |
过滤选择器(仅常用)
选择器 | 描述 | 返回 | 示例 |
:first | 选取第一个元素 | 单个元素 | $(‘div:first’),选取所有div元素中的第一个元素 |
:last | 选取最后一个元素 | 单个元素 | $(‘div:last’),选取所有div元素中的最后一个元素 |
:not(el) | 除去指定元素外的元素 | 元素的集合 | $(‘div:not(.test)’),选取所有div元素,但是类名是test的div除外 |
:even | 所有索引是偶数的元素,索引从0开始 | 元素的集合 | $(‘div:even’),获取所有的div元素,选中其中所有索引是偶数的div |
:odd | 所有索引是奇数的元素,索引从0开始 | 元素的集合 | $(‘div:odd’),获取所有的div元素,选中其中所有索引是奇数的div |
:eq(index) | 选取索引等于index的元素,索引从0开始 | 单个元素 | $(‘div:eq(10)’),获取所有的div元素,选中其中索引等10的div |
:gt(index) | 选取索引大于index的元素,索引从0开始 | 元素的集合 | $(‘div:gt(2)’),获取所有的div元素,选中其中索引等大于2的div |
:lt(index) | 选取索引小于index的元素,索引从0开始 | 元素的集合 | $(‘div:lt(5)’),获取所有的div元素,选中其中索引等小于5的div |
:header | 选取所有的标题元素,例如h1,h2 | 元素的集合 | $(’:header’),选取网页上所有的h1,h2…等等 |
:animated | 选取正在执行动画的所有元素 | 元素的集合 | $(‘div:aninated’),选中所有正在执行动画的div元素 |
:hidden | 选取所有不可见元素 | 元素的集合 | (‘input:hidden’) |
:visiable | 选取所有可见元素 | 元素的集合 | $(‘div:visible’)选中所有可见的div元素 |
[attr] | 选中拥有此属性的元素 | 元素的集合 | $(‘div[id]’)选取拥有id属性的元素 |
[attr=value] | 选中属性值为value的元素 | 元素的集合 | $(‘div[title=test]’),选取属性title值为"test"的元素 |
[attr!=value] | 选中属性值不等于value的元素 | 元素的集合 | $(‘div[title!=test]’),选取属性title值不为"test"的元素,注意:假如元素没有title属性,也会被选中 |
[attr^=value] | 属性值以value开头 | 元素的集合 | $(‘div[title^=test]’),选取的元素有title属性,并且title属性的值是以test开头的 |
[attr$=value] | 属性值以value结尾 | 元素的集合 | $(‘div[title^=test]’),选取的元素有title属性,并且title属性的值是以test结尾的 |
[attr*=value] | 属性值中包含value | 元素的集合 | $(‘div[title^=test]’),选取的元素有title属性,并且title属性的值包含了test这个字符串 |
[attr1][attr2][attr3] | 复合过滤器,将多个过滤组合在了一起,选中的元素必须同时满足要求 | 元素的集合 | $(‘div[id][title^=test]’),选中的div,必须有id属性,并且必须有title属性,同时title属性的值必须以test开头 |
:nth-child(index/even/odd/eq) | 选中每个父元素下的第index个子元素或者奇偶数 | 元素的集合 | :eq(index)获取的是单个元素,nth-child将为每一个父元素匹配子元素,并且nth-child是从1开始算的,eq(index)的index是从0开始算的:nth-child(even),所有父元素下的索引值是偶数的元素:nth-child(odd),所有父元素下的索引值是奇数的元素:nth-child(2n),所有父元素下的索引值是2的倍数的元素:nth-child(3n),所有父元素下的索引值是3的倍数的元素:nth-child(3n+1),所有父元素下的索引值是3n+1的元素 |
:first-child | 每个父元素的第一个子元素 | 元素的集合 | $(‘ul li:first-child’),选中页面上每个ul元素下的第一个li元素 |
:last-child | 每个父元素的最后一个子元素 | 元素的集合 | $(‘ul li:last-child’),选中页面上每个ul元素下的最后一个li元素 |
:only-child | 如果某个元素是它父元素中唯一的子元素,则被选中 | 元素的集合 | $(‘ul li:only-child’),选中页面上每个ul元素下唯一的li元素,换句话说,这个li必须是ul中唯一的子元素 |
:enable | 所有可用的元素 | 元素的集合 | $(’#form:enable’),选取id为form中所有可用的元素 |
:disabled | 所有不可用的元素 | 元素的集合 | $(’#form:disable’),选取id为form中所有不可用的元素 |
:checked | 所有被选中的元素,必须单选和多选 | 元素的集合 | $(‘input:checked’),选取所有被checked的input元素 |
:selected | 所有被选中的选项元素,比如下拉菜单 | 元素的集合 | $(‘select:selected’),选取所有被selected的select元素 |
:input | 选取所有的input,textarea,select,button | 元素的集合 | $(’:input’) |
:text | 选中所有的单行文本 | 元素的集合 | $(’:text’) |
:password | 选中所有的密码框 | 元素的集合 | $(’:password’) |
:radio | 选中所有的单选框 | 元素的集合 | $(’:radio’) |
:checkbox | 选中所有的复选框 | 元素的集合 | $(’:checkbox’) |
:submit | 选中所有的提交按钮 | 元素的集合 | $(’:submit’) |
:image | 选中所有的图像按钮 | 元素的集合 | $(’:image’) |
:reset | 选中所有的重置按钮 | 元素的集合 | $(’:reset’) |
:button | 选中所有的按钮 | 元素的集合 | $(’:button’) |
:file | 选中所有的上传域 | 元素的集合 | $(’:file’) |
:hidden | 选中所有的不可见元素 | 元素的集合 | $(’:hidden’) |
选择器中的注意事项
特殊字符
假如选择器中选择的属性值有特殊字符,比如#,[]等这些,那么就需要使用转义,否则会报错,比如:
$('#id#b') //这样是会报错的
$('#id\\#b') //需要的#转义
$('#id[1]') //这样是会报错的
$('#id\\[1\\]') //需要转义
引号问题
$('#id[title="test"]')
空格问题
选择器中空格是有自己的含义的,代表后代
$('.test :hidden') //选中的是类名中带有test的元素的后代元素中隐藏的元素节点
$('.test:hidden') //选中的是所有类名中带有test并且被隐藏的元素
DOM操作
对DOM的操作流程就是两步,第一步:找到要操作的元素节点;第二步:对元素节点进行修改编辑操作;
查找元素节点
通过上面的选择器,就可以将所有需要的元素获取到;
对元素节点的操作
元素节点的属性
方法 | 描述 | 示例 |
.attr() | 获取元素节点的属性或者对元素节点进行属性设置 | 获取:(’.class’).attr(‘title’,‘10’),将所有类名中包含class的元素的title值设置成10同样,也可以通过attr()方法,对元素节点的class进行操作,比如:$(’.test’).attr(‘class’,‘title’),注意:设置不是添加,并不会对class的值进行追加title,而是将class的值整体替换成title。 |
.removeArrt() | 将元素节点的某个属性删除 | $(’.class’).removeAttr(‘title’),将所有类名中包含class的元素删除上面的title属性 |
元素节点操作
方法 | 描述 | 示例 |
$(’<li title=“10”></li>’) | 使用$()方法,将一对HTML标记包裹起来就可以创建一个DOM对象,之后通过节点添加的方法将元素节点加入指定的dom中 | let title = ‘<h1 title=“10”>标题</h1>‘let $title = (’.class’).append(KaTeX parse error: Undefined control sequence: \< at position 71: …如:let title = '\̲<̲h1 title="10"\>…(’.class’).append(title); |
append() | 向每个匹配的元素内部追加内容,追加的内容会被放在元素内部的最后面 | $(’.class’).append(’<h1 title=“10”>) |
appendTo() | 将内容,添加在指定元素的内部的最后面,与append的区别在于,$(a).append(b),是将b添加到a里面,appendTo则正好相反,是将a添加到b里面 | $(’<h1 title=“10”>).append(’.class’) |
prepend() | 向每个匹配的元素内部追加内容,追加的内容会被放在元素内部的最前面 | $(’.class’).prepend(’<h1 title=“10”>) |
prependTo() | 将内容,添加在指定元素的内部的最前面,与prepend的区别在于,$(a).prepend(b),是将b添加到a里面,prependTo则正好相反,是将a添加到b里面 | $(’<h1 title=“10”>).prepend(’.class’) |
after() | 向所有匹配的元素的后面添加指定内容,与append等不同的是,追加的位置不是内部,而是外部,是同级元素 | $(’.class’).after(’<h1 title=“10”>)//添加后的示例<div class=‘class’></div><h1 title=‘10’></h1> |
insertAfter() | 将内容,添加在指定元素的后面,与after的区别在于,$(a).after(b),是将b添加到后面,insertAfter则正好相反,是将a添加到b后面 | $(’<h1 title=“10”>).insertAfter(’.class’) |
before | 向所有匹配的元素的前面添加指定内容,与append等不同的是,追加的位置不是内部,而是外部,是同级元素 | $(’.class’).before(’<h1 title=“10”>)//添加后的示例<h1 title=‘10’></h1><div class=‘class’></div> |
.remove() | 将选择的节点删除(包括这个节点的子元素),这个方法会有一个返回值,返回值是被删除节点元素,另外这个方法可以有参数,参数的方式和选择器书写规则一样,可以进一步限定删除元素的范围 | $(’.class’).remove(),将所有类名中有class的元素以及其子元素全部删除,示例1:let li = (‘ul li:eq(2)’).remove(),先获取ul li下第二个子元素,然后将其在DOM树中删除示例2:(‘ul li’).remove(‘li[title=菠萝]’),将所有ul下的li中title值等于“菠萝”的li删除 |
.empty() | 与其说是删除节点,不如说是清空指定节点里面的所有子元素 | $(‘ul li’).empty(),将所有ul下li里面的所有子元素全部清空(不包含li本身,是li里面的所有子元素) |
.clone() | 这个方法有一个参数,是一个布尔值,当为true的时候,是进行深度拷贝,包括绑定在上面的事件等也会被一起拷贝,如果不写参数,则仅仅是拷贝html结构 | KaTeX parse error: Expected '}', got 'EOF' at end of input: …ick(function(){(this).clone().appendTo(’#test’)})为ul 下所有的li添加点击事件,点击后将本li以及其子元素添加到id为test的元素内 |
replaceWith() | 将所有选定元素节点替换成指定内容 | $(‘p’).replaceWith(<h1>你好</h1>’),将所有p元素替换成<h1>你好</h1> |
replaceAll() | 将所有指定内容替换元素,与replaceWith()的区别在于,(a).replaceAll(b)则正好完全相反,是将a全部替换掉b | $(’<h1>你好</h1>’).replaceWith(‘p’),将所有p元素替换成<h1>你好</h1> |
.wrap() | 将所有匹配的元素每一个单独用指定的标签包裹 | $(‘strong’).wrap(’<b><b/>’),将每一个strong标签用b标签包裹 |
.wrapAll() | 将匹配到的元素统一包裹,区别在于,wrap是每一个都单独包裹,而wrapAll则是如果有多个连续在一起,则统一打包 | $(‘strong’).wrapAll(’<b><b/>’)示例,执行后:<b><strong>1</strong><strong>1</strong></b> |
.wrapInner() | 将匹配元素的内部的所有内容一起包裹 | $(‘strong’).wrapInner(’<b><b/>’)示例:<strong><b>1</b></strong> |
样式操作
方法 | 描述 | 示例 |
adClass() | 对选择的jquery对象进行追加样式,也就是在原来的class值上添加新的值,如果添加多个,那么就用空格间隔,比如addClass(‘test1 test2’) | <li class=‘title’></li>//对所有类名中包含title的元素节点追加类名test$(.title’’).addClass(‘test’)//追加后<li class=‘title test’></li> |
removeClass() | 对选择的jquery对象进行删除样式,如果删除多个,那么就用空格间隔,比如removeClass(‘test1 test2’) | <li class=‘title test’></li>//对所有类名中包含title的元素节点删除类名test$(.title’’).addClass(‘test’)//删除后<li class=‘title’></li> |
toggleClass() | 来回切换样式,如果目标元素上的指定类名存在,就删除,如果类名不存在,就添加 | $(.title’’).toggleClass(‘test’) |
hasClass() | 判断某个类名是否存在,返回值是一个布尔值,如果存在返回true,如果不存在返回false | //判断.title上是否有类名test,如果有,返回true,如果没有返回false$(.title’’).hasClass(‘test’) |
设置和获取HTML、文本和值
方法 | 描述 | 示例 |
html() | 类似js中的innerHTML方法,可以设置某个元素的HTML内容,注意,该方法会将选中的元素节点内部的所有内容替换成指定的内容 | //设置HTML(’.test’).html() |
text() | 设置或获取指定元素下的文本内容,和html()不同的是,html()获取的内容包括HTML标记,而text()则只获取文字内容,不会获取HTML标记 | //设置$(’.test’).text(‘你好’)//获取let html = $(’.test’).text() |
val() | 设置或获取元素的value值,比如下拉选择,单选框,输入框,多选框的value值 | //设置$(‘input’).val(‘title’)//获取let val = $(‘input’).val() |
遍历节点
方法 | 描述 | 示例 |
children() | 遍历指定元素节点下的所有子节点,可以设置参数增加限定条件,注意:仅仅是子节点,不包括孙节点以及再往下的后代元素节点 | //找到所有类名中包含类名test的元素下的所有子节点,然后为其设置了一个title属性,值为你好(’.test’).children(‘div’).attr(‘title’,‘你好’) |
next() | 找到指定元素的下一个节点,注意是同级元素 | //找到所有类名中包含类名test的元素下一个同级元素,然后为其设置了一个title属性,值为你好$(’.test’).next().attr(‘title’,‘你好’) |
prev() | 找到指定元素的上一个节点,注意是同级元素 | //找到所有类名中包含类名test的元素上一个同级元素,然后为其设置了一个title属性,值为你好$(’.test’).prev().attr(‘title’,‘你好’) |
siblings() | 找到指定元素节点的所有其他同级元素(不包括选定节点) | //找到所有类名中包含test的元素的所有其他同级元素,为其设置title属性,值为你好$(’.test’).siblings().attr(‘title’,‘你好’) |
CSS-DOM
简单的说就是获取或者设置对象的CSS样式
css() | 可以获取或者设置指定元素的style样式,假如设置的css样式中带有“-”,比如font-size,那么就使用驼峰写法,将首字母大写,比如写成:fontSize | let color =(’.test’).css(‘fontSize’,‘18px’),$(’.test’).css({‘fontSize’:‘18px’,‘color’:’#888888’}) |
height() | 可以获取或者设置指定元素的高度 | 获取let height =(’.test’).height(100) |
width() | 可以获取或者设置指定元素的宽度 | 获取let width = (’.test’).width(100) |
offset() | 这个方法有两个属性,可以获取指定元素的相对于窗口的偏移量,也就是距离顶部多少距离,距离左侧多少距离 | //左侧(’.test’).offset().top |
position() | 这个方法也有两个属性,获取的是相对于最近一个position属性是relative或者absolute属性的左侧和顶部距离 | //左侧(’.test’).position().top |
scrollTop() | 元素滚动条距离顶部的距离,常用在元素内容高度超出视窗内容时,出现滚动条,点击按钮按钮后滚动到指定位置 | //滚动条滚动到高度100px的位置$(’.test’).scrollTop(100) |
jQuery中的事件和动画
加载DOM
//javascript
window.onload={
...
}
//jq
$(document).ready(function(){
...
})
//简写
$(function(){
...
})
区别:
window.onload会在这个文档全部加载完成后执行,包括图片加载,如果写有多个window.onload,那么后面的会覆盖前面的,前面先写的将不再执行;
$(function())会在DOM加载结束后就会执行,不需要等到图片全部下载完成,如果写多个,将逐一执行,并不会产生后面的覆盖前面的清空;
事件绑定
on() | 两个参数,第一个是事件类型,第二个是事件触发之后的回调函数;多个事件可以用空格隔开;第一个事件类型有:blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error | //绑定点击事件,也就是元素点击之后会触发第二个函数(’.test’).on(‘mouseover mouseout’,function(){}) |
off() | 为绑定事件的对象解除绑定,可以有参数,参数是绑定的函数名,如果不传函数名,那么会将对象上绑定的所有事件一起清除 | //解绑所有绑定事件(’.test’).on(‘click’,fn1=function(){})$(’.test’).off(‘click’,‘fn1’) |
one() | 只能生效一次的事件 | //.test的点击事件只有第一次点击有效,之后点击无效$(’.test’).one(‘click’,fn1=function(){}) |
hover(enter,leave) | 这是一个合成事件,模拟了鼠标的悬浮事件,有两个参数,风别是两个方法,第一个是鼠标移入时触发的方法,第二个是鼠标移出时触发的方法 | $(’.test’).hover(function(){},function(){}) |
toggle(fn1,fn2,…funN) | 这也是一个合成事件,每一次单击元素会逐一触发里面的函数,比如点击一次触发fn1,点击第二次触发fn2,第N次触发fnN,之后再从fn1开始循环触发 | $(’.test’).toggle(function(){},function(){}) |
event.stopPropagation() | 阻止事件冒泡 | $(’.test’).on(‘click’,function(event){event.stopPropagation()}) |
event.preventDefault() | 阻止默认事件 | $(’.test’).on(‘click’,function(event){event.preventDefault()}) |
event.type | 获取当前事件类型 | $(’.test’).on(‘click’,function(event){//返回的是clickevent.type;}) |
event.target | 获取当前触发事件的元素 | $(’.test’).on(‘click’,function(event){//返回的是当前.test这个元素event.target;}) |
event.pageX | 当前光标处于页面的x坐标 | $(’.test’).on(‘click’,function(event){event.pageX;}) |
event.pageY | 当前光标处于页面的y坐标 | $(’.test’).on(‘click’,function(event){event.pageY;}) |
trigger() | 模拟事件,打开页面后,模拟用的某个某个操作,当然模拟是指模拟操作,操作后执行的代码还是要正常写的,比如,模拟了一个点击按钮,点击之后执行的函数要正常写注意:该方法会执行浏览器的默认操作,比如$(‘input’).trigger(‘focus’);input会执行focus事件,并且会得到焦点 | //模拟用户点击了按钮$(’.test’).trigger(‘click’) |
triggerHandler() | 执行事件,但是不会触发默认操作。比如上面的input的focus事件,input会执行focus事件,但是不会得到焦点 | $(‘input’).triggerHandler(‘focus’) |
命名空间
为事件可以添加命名空间,这样删除事件时只需要删除指定的命名空间即可
//这个.plugin就是命名空间
$('.test').on('click.plugin',function(event){})
//.test上点击事件的第二个命名空间
$('.test').on('click.aaa',function(event){})
//.test上点击事件没有命名空间
$('.test').on('click',function(event){})
因此,删除上面的某一个点击事件,只需要
//只删除了.aaa这个点击事件,没有命名的和不同命名的事件都不会被删除
$('.test').off('.aaa')
因此模拟点击事件的时候需要触发指定的命名空间的点击事件
//click后面的感叹号!,就是匹配不包含在命名空间的click方法
$('.test').trigger('click!')
//如果需要匹配所有的click,正常模拟就可以了
$('.test').trigger('click')
动画
show() | 将对象的display的值改成block,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当show()函数完全执行完毕后执行的函数 | $(’.test’).show(1500,function(){}) |
hide() | 将对象的display的值改成none,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当hide()函数完全执行完毕后执行的函数 | $(’.test’).hide(1500,function(){}) |
fadeIn() | 将对象的透明度opacity逐渐改变至完全显示,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当fadeIn()函数完全执行完毕后执行的函数 | $(’.test’).fadeIn(1500,function(){}) |
fadeOut() | 将对象的透明度opacity逐渐改变至完全隐藏,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当fadeOut()函数完全执行完毕后执行的函数 | $(’.test’).fadeOut(1500,function(){}) |
slideUp() | 只会改变对象的高度,将对象的高度由下至上隐藏,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当slideUp()函数完全执行完毕后执行的函数 | $(’.test’).slideUp(1500,function(){}) |
slideDown() | 只会改变对象的高度,将对象的高度由上至下显示,参数一共有两个,第一个可以是规定的关键字,slow,normal,fast也可以是具体的毫秒,第二个是回调函数,也就是当slideDown()函数完全执行完毕后执行的函数 | $(’.test’).slideDown(1500,function(){}) |
animate() | 自定义动画这个函数最为强大,上面写的三对都是改变单一属性,而这个可以自定义多个属性同时生效;**语法结构:**animate(params,speed,callback)params:是一个包含样式属性和值的对象,比如{height:‘show’,opacity:‘show’}speed:速度,可选callback:动画执行完毕后执行的函数 | $(’.test’).animate({{height:‘show’,opacity:‘show’},1500,function(){})//animate可以执行累加或者累减的计算,具体看例子 |
.stop() | 停止正在执行的动画,说到这个,就要先说到动画的执行队列,每一次jq在执行动画的时候,都会将动画放入一个队列中,依次执行,很多时候动画还没有结束,但是事件以及结束了,比如:鼠标移入移出动画,鼠标移入的时候触发了一个动画,但是动画还没有结束,鼠标就移出了,此时还要等到移入的动画结束才可以执行移出的动画,这显然是很不科学的,因此可以通过.stop()方法,将正在执行的动画结束掉,执行新的动画 | $(’.test’).stop().animate({left:‘300’},200) |
is(’:animated’) | 判断元素是否处于动画状态,实际用处时,很多时候要避免动画的累积,比如上例中说的鼠标移入移出,如果快速来回多次移入移出鼠标,那么动画将会累积,如果不用stop(),那么可以判断当前元素动画是否正在执行,如果当前元素正在执行动画,那么就不需要再添加动画了 | if(!$(element).is(’:animated’)){//如果没有执行动画,添加新动画} |
toggle() | 切换元素的可见状态,相当于把hide()和show()组合起来了 | $(’.test’).toggle() |
slideToggle() | 切换元素的高度状态,相当于将slideUp()和slideDown()组合起来了 | $(’.test’).slideToggle() |
fadeTo() | 该方法可以将元素的不透明度切换至指定状态 | $(’.test’).fadeTo(600,0.2) |
累加或者累减动画
//每一次对.test元素进行点击,它离左侧的距离就增加500px
$('.test').on('click',()=>{
$(this).animate({left:'+=500'},300)
})
//每一次对.test元素进行点击,它离左侧的距离就减少200px
$('.test').on('click',()=>{
$(this).animate({left:'-=200'},300)
})
jQuery对表单,表格的操作
.focus() | 这个方法其实和css选择器中的:focus类似,但是ie6不支持除hover之外的选择器,因此可以使用这个代替,具体功能就是当聚焦时触发函数 | $(‘input’).focus(function(){}) |
复选框的全选,反选,和全不选
//全选
$('[name=item]:checkbox').attr('checked',true)
//全不选
$('[name=item]:checkbox').attr('checked',false)
//反选
$('[name=item]:checkbox').each(()=>{
$(this).attr('ckecked',!$(this).attr('ckecked'))
})
包含指定文本内容高亮
//通过选择器:contains实现
$('tr:contain("王五")').addClass('selected')
本节实际上书上并没有什么特殊的内容,只是讲了一些表格中针对元素操作时会使用到的方法,而这些方法就是前文中说到的那些,只是做了一个组合,因此没有实际的新内容,表格表单的部分会在后面只做一个实例:表单插件的篇幅中实际使用;
jQuery和Ajax
load(url [,data] [,callback])
- url:请求的HTML页面的URL地址;
- data:可选,发送至服务器的key/value;
- callback:可选,请求完成后执行的回调函数;
通常使用在将html页面加载到指定位置,比如:后台管理页面,根据导航按钮,在右侧或右侧加载指定的页面,实现不刷新页面的情况下加载不同的内容
如果第二个data,没有参数,那么默认采用GET的方式,如果有会自动转成POST方式
**
//点击类名为btn的元素后,在id为test的元素内加载了testHtml页面
$('.btn').on('click',function(){
$('#test').load('testHtml.html')
})
//GET方式
$('#test').load('testHtml.html',function(){})
//POST方式
$('#test').load('testHtml.html',{name:'rain',age:'22'},function(){})
$.get(url [,data] [,callback] [,type])
- url:请求的URL地址;
- data:可选,发送至服务器的key/value数据会作为QueryString附加到请求的URL中;
- callback:可选,载入成功时回调函数(只有当Response的返回状态是success才会调用该方法)自动将请求结果和状态传递给该方法;
- type:可选,服务器端返回内容的格式,默认不填jq会自行判断内容的格式,比如:xml,html,script,json,text和_default;
//点击类名为btn的元素后,在id为test的元素内加载了testHtml页面
$('.btn').on('click',function(){
$.get('服务器地址',{
user:$('#userInput').val(),
content:$('#content').val()
},function(data,status){
//data,请求结果后返回的数据
//status,请求返回的状态
$('#div').html(data)
})
})
$.post(url [,data] [,callback] [,type])
.get()的用法基本一致,唯一的区别在于提交的方式,一个是GET一个是POST,题外话:
POST和GET的区别:
- GET请求会讲参数跟在URL后面发送至服务器,而POST的参数会放在HTTP的消息体中传递,相对而言,POST的参数要隐藏的好一点,但如果是有心人的话都不太可靠;
- GET方式对传输的数据大小有限制,通常不能超过2KB,POST理论上没有限制;
- GET的方式请求的数据会被浏览器缓存起来,因此其他人可以从浏览器的历史记录中读取这些数据,假如账号密码是用GET请求的,那么账号密码也会被缓存,而POST的请求数据不会被缓存,这一点上看如果数据对安全性有一定要求,那么要用POST发送请求;
//点击类名为btn的元素后,在id为test的元素内加载了testHtml页面
$('.btn').on('click',function(){
$.post('服务器地址',{
user:$('#userInput').val(),
content:$('#content').val()
},function(data,status){
//data,请求结果后返回的数据
//status,请求返回的状态
$('#div').html(data)
})
})
$.getScript(url,success(response,status))
通过 AJAX 请求来获得并运行一个 JavaScript 文件
- url:url地址
- success:回调函数,会在javaScript文件成功载入后运行,有两个参数,第一个是返回的数据,第二个是返回的状态
//点击类名为btn的元素后,加载了一个test.js的js文件
$('.btn').on('click',function(){
$.getScript('xxx/test.js',function(data,status){
//data,请求结果后返回的数据
//status,请求返回的状态
$('#div').html(data)
})
})
$.getJSON(url,success(response,status))
getJSON() 方法使用 AJAX 的 HTTP GET 请求获取 JSON 数据
- url:url地址
- data:可选,发送的数据
- success:回调函数,会在javaScript文件成功载入后运行,有两个参数,第一个是返回的数据,第二个是返回的状态
//点击类名为btn的元素后,加载了一个test.js的js文件
$('.btn').on('click',function(){
$.getJson('xxx/test.json',function(data,status){
//data,请求结果后返回的数据
})
})
$.ajax(option)
这个是jq中最底层的Ajax方法,其他所有的方法都是用这个方法实现的,option一共有以下参数:
参数 | 类型 | 说明 |
url | String | 请求数据的服务器地址 |
type | String | 请求数据的方式,是用POST还是用GET,默认是GET |
timeout | Number | 请求的超时时间,单位毫秒 |
data | Object或者String | 发送到服务器的数据,可以是一个对象也可以是个字符串,需要跟后台开发人员协定 |
dataType | String | 预期返回的数据类型,如果不指定,那么jQuery将自动根据Http包含的信息进行判断类型有:xml:xml文档html:html信息,如果是包含script的html,那么script会在插入DOM时运行script:返回的纯文本javaScript代码,不会自动缓存结果json:json数据jsonp:JSONP格式text:纯文本字符串 |
beforeSend | Function | 发送请求钱可以修改XMLHttpRequest对象的函数,比如可以添加自定义的请求头 |
complete | Function | 请求完成后调用的回调函数,无论请求成功还是请求失败 |
success | Function | 请求成功后的回调函数,这个函数默认有两个参数:第一个:服务器返回的数据第二个:返回数据的状态字符串 |
error | Function | 请求失败后的回调函数,这个函数有三个默认的参数:第一个:XMLHttpRequest对象第二个:错误信息第三个:可选,捕获的错误对象 |
global | Boolean | 默认是true,代表是否触发全局的Ajax时间,具体事件看下一章节 |
//点击类名为btn的元素后,发送了一个请求
$('.btn').on('click',function(){
$.ajax({
type:'POST', //指定方式是POST,否则默认是GET
url:'test.js', //服务器地址
data:{ //数据
name:'yzq',
content:'测试'
},
success(data,status){
//请求成功是触发的函数
},
error(xml,status,error){
//请求失败是触发的函数
}
})
})
jQuery中的Ajax全局事件
全局事件,个人理解就是当页面上只要发生Ajax请求,就会根据情况触发
方法 | 描述 | 示例 |
.ajaxStart() | 任意ajax请求开始时触发,比如请求开始时需要触发加载中的加载动画 | KaTeX parse error: Expected '}', got 'EOF' at end of input: …art(function(){(’#loading’).show()}) |
.ajaxStop() | 任意ajax请求结束时触发,比如结束时需要将加载框隐藏 | $(document).ajaxStart(function(){ $(’#loading’).hide()}) |
.ajaxComplete() | 任意ajax请求完成时触发,这个和ajaxStop()基本类似 | KaTeX parse error: Expected '}', got 'EOF' at end of input: …ete(function(){(’#loading’).hide()}) |
.ajaxError() | 任意ajax请求发生错误时执行 | $(document).ajaxComplete(function(){alert(‘请求错误了’)}) |
.ajaxSend() | 任意ajax请求发送前执行必需。规定当请求成功时运行的函数。额外的参数:event包含 event 对象xhr - 包含 XMLHttpRequest 对象options - 包含 AJAX 请求中使用的选项 | $(document).ajaxSend(function(e,xhr,opt){alert(‘请求错误了’)}) |
.ajaxSuccess() | 任意ajax请求成功时执行的函数 | $(document).ajaxComplete(function(){ alert(‘请求成功了’)}) |
插件的使用和写法
插件也称为扩展,是一种遵循一定规范的应用程序接口编写的程序;
插件的种类
大致可以分为三种:
- 封装对象方法的插件:这种就是将对象方法封装起来,然后通过jQuery对象进行操作,比如jQuery自带的parnet(),addClass()等等操作DOM的方法,都是此类;
- 封装全局函数插件:可以将独立的函数驾到jQuery命名空间下,比如常用的.trim()方法等;
- 选择器插件:个别情况下,会需要用到选择器插件,虽然jQuery的选择器十分强大,但还是需要扩展的;
基本要点
- jQuery插件的文件命名规则为:jquery.自定义名字.js,比如:jq.color.js;
- 所有对象的方法都应该附加到jQuery.fn对象上,而所有的全局函数都应该附加到jQuery本身上;
- 在插件内部,this指向的是当前通过选择器获取的jQuery对象,而不像一般方法那样指向的是DOM元素;
- 可以通过this.each遍历所有元素;
- 所有的方法或函数插件,都应该以分号结尾,否则压缩的时候可能出现问题,为了更稳妥写,甚至可以在插件头部页加上一个封号;
- 插件应该返回一个jQuery对象,以保证插件可以链式操作,除非插件需要返回的是一些需要获取的量,例如字符串或者数组等;
- 避免在插件内部使用$作为jQuery对象别名,而应该使用完整的jQuery来表示,这样可以避免冲突。当然也可以利用必报这种技巧来回避这个问题;
模版格式
//书上推荐
;(function($){
//这里是插件代码
let foo;
let bar = function(){}
//将函数添加到$对象上
$.BAR = bar;
})(jQuery)
用一个立即执行函数,将真正的插件代码分离在函数体内部,这样就不用担心变量污染的情况,写在函数体内的变量外部访问不到,然后通过给$对象也就是jQuery对象添加属性BAR使得外界可以访问函数bar;
插件的机制
jQuery提供了两个用于扩展jQuery功能的方法,即**jQuery.fn.extend()方法和jQuery.extend()**方法,这两个方法都接收一个Object对象作为参数;
jQuery.fn.extend()
用于扩展三种类型插件中的第一种,比如现在要做一个color()插件,该插件有两个功能
- 为匹配元素设置颜色
- 获取匹配元素中的第一个元素的颜色
;(function($){
$.fn.extend({
color:function(value){
//插件代码
//判断是否有value,如果有传入value值,那么就代表是设置,如果没有那么就代表是获取
if(!value){
//此处的this,指向的是当前调用该方法的DOM元素
return this.css('color');
}
else{
return this.css('color',value);
}
}
})
})(jQuery)
jQuery.extend()
用于扩展后两种插件以及拥有一个十分强大的功能:扩展已有的Object对象;
//这个方法会讲obj1,obj2等等对象合并到target对象上,如果有相同的属性名,那么后面的就会覆盖前面的
jQuery.extend(target,obj1,obj2,...,objN);
因此,jQuery.extend()经常用于设置插件方法的一系列默认参数,比如:
//.test上调用validata()方法,并传递过去了一个对象
$('.test').validate({
name:'bar',
length:5
})
//插件
;(function($){
let DEFAULT_OPTION={
name:'BAR'
}
$.fn.extend({
validate:function(option){
//如果用户有传配置,那么配置中的配置项将覆盖默认配置,如果没有传,那么就将启用默认配置
let newOption = jQuery.extend(DEFAULT_OPTION,option)
})
})(jQuery);
如果是需要对现有的全局方法进行扩展,那么就可以这样
;(function($){
$.extned({
ltrim:function(text){
return (text||'').replace(/^\s+/g,"");
}
})
})(jQuery);
//调用
jQuery.ltrim(' test ')
案例
制作一个轻量级表单验证的插件,要求:
- 可以验证不同类型的输入框,至少要有以下几种验证:手机号,身份证号,邮箱,必填项;
- 可以自定义验证规则,如果没有自定义,那么将启用默认验证规则;
;(function(root,func,plugIn){
func(jQuery,plugIn);
})(this,function(jQuery,plugIn){
var DEFAULTS = {
plugInName:"dv",
initEvent:"input",
initError:"您输入的信息有误,请仔细检查",
initRequired:"该输入为必填项",
//功能诉求
rules:{
"email":/^\w+@\w+\.\w+$/,
"mobile":/^1\d{10}$/,
"password":/^\w{8,16}$/,
"landline":/^\d{3,4}-\d{7,8}$/
}
}
$.fn[plugIn] = function (option) {
var _this_ = this;
//检测是不是form调用的该方法,如果不是,直接返回
if(!_this_.is("form")){
return _this_;
}
//如果是form
var NEW_DEFAULTS = objExtend(DEFAULTS,option);
$.extend(_this_,NEW_DEFAULTS);
_this_.$finds = _this_.find("input");
_this_.$finds.on(_this_.initEvent,function(){
var _this = $(this);
_this.siblings('p').remove();
// console.log(this);
var $required = _this.data(_this_.plugInName+"-required");
if(isBoolean($required) && isRequired.call(_this)){
_this.after("<p style='color:red;margin-top:5px'>"+_this_.initRequired+"</p>")
}
else{
$.each(_this_.rules,function(key,fn){
var $findName = _this.data(_this_.plugInName+"-"+key);
var $error = _this.data(_this_.plugInName+"-"+key+"-error");
if($findName){
var result = testRegExp.call(_this,_this_.rules[key])
$error = $error || _this_.initError;
if(!result){
_this.after("<p style='color:red;margin-top:5px'>"+$error+"</p>")
}
}
})
}
})
//规格合并
function objExtend(target,source){
if(!(isObj(target)&&isObj(source))){
return this;
}
var targetKeys = Object.keys(target);
targetKeys.forEach(function(index){
if(!isObj(target[index])){
target[index] = source[index]?source[index]:target[index];
}
else{
target[index] = isObj(source[index])? copyTarget(target[index],source[index]):target[index];
}
})
return target;
}
/**
* 正则合并
* */
function copyTarget(target,source){
if(!(isObj(target)&&isObj(source))){
return this;
}
for(var i in source){
if(isRegExp(source[i])){
target[i] = source[i]
}
}
return target;
}
/**
* 检测正则
* */
function testRegExp(reg){
if(!isRegExp(reg)){
return this;
}
return reg.test(this.val());
}
/**
* 必填检测
*/
function isRequired(){
return this.val() === ''
}
function isObj(obj){
return Object.prototype.toString.call(obj) === "[object Object]";
}
function isRegExp(reg){
return Object.prototype.toString.call(reg) === "[object RegExp]";
}
function isBoolean(boolean){
return Object.prototype.toString.call(boolean) === "[object Boolean]";
}
}
},"validate")
附录
jQuery的性能优化
- ID选择器>标签选择器>类选择器>属性选择器
- 使用缓存对象,尽量不要没做一次DOM操作使用选择器获取一次DOM,当然如果使用的是链式操作那就没有问题,比如:
let dom = $('#id');
dom.css('color','#333333');
dom.on('click',function(){})
//或者
dom.css('color','#333333').on('click'.function(){})
- 循环操作DOM时,可以等循环结束一次性插入DOM,比如:
//比如有数组的长度100,需要将每一项都制成li插入ul,
//那么最好不要没循环一次就插入一次DOM,这样插入100次
//可以这样,先将数组遍历一遍,将内容以字符串的方式存储,之后一次性插入DOM
let list = [...];
let strLi = '';
for(let i = 0;i<list.length;i++){
strLi += '<li>'+list[i]+'</li>'
}
$('#id').html(strLi);
- 使用事件代理,而不是每一个元素绑定事件
$(table).on('click',function(e){
let target = $(e.target);
//...
})
- 为了更好的重用,一个功能尽量打包成插件
jQuery技巧
- 禁用右击
$(function(){
$(document).on('contextmenu',function(e){
return false;
})
})
- 判断元素是否存在
//通过length判断是否存在
if($('#id').length){
//do someing
}