《锋利的jQuery》再次阅读及摘要

前言

在如今的前端框架潮流中,毫无疑问React,Vue已经走在了第一线,越来越多前端开发者加入其中,但是昔日的霸主jQuery依然不可小视,在过去一年的调研中(原文:https://yq.aliyun.com/articles/716657?spm=a2c4e.11163080.searchblog.9.9a0f2ec1Ks6owj)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对象只需要使用 ( ) D O M ()方法将DOM对象包裹起来,比如 (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 选取所有不可见元素 元素的集合 ( : h i d d e n ) i n p u t 使 (':hidden')选取的是所有不可见的元素,其中包括了:如果仅仅是需要选中input中的不可见元素,那么可以使用 (‘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() 获取元素节点的属性或者对元素节点进行属性设置 获取: ( . c l a s s ) . a t t r ( t i t l e ) c l a s s t i t l e ('.class').attr('title'),获取是所有类名中包含class的元素中的**第一个元素**的title值**设置:** (’.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 = ( t i t l e ) (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 ) . r e p l a c e W i t c h ( b ) b a (a).replaceWitch(b),是将所有b替换掉a,而 (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 ( . t e s t ) . h t m l ( ) / / H T M L l e t h t m l = ('.test').html('你好')//获取HTMLlet 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属性,值为你好 ( . t e s t ) . c h i l d r e n ( ) . a t t r ( t i t l e , ) / / t e s t d i v t i t l e ('.test').children().attr('title','你好')//找到所有类名中包含类名test的元素下的所有子节点,只为其中的div元素设置了一个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 = ( . t e s t ) . c s s ( c o l o r ) , ('.test').css('color'), (’.test’).css(‘fontSize’,‘18px’),$(’.test’).css({‘fontSize’:‘18px’,‘color’:’#888888’})
height() 可以获取或者设置指定元素的高度 获取let height = ( . t e s t ) . h e i g h t ( ) p x ('.test').height()设置,默认单位是px, (’.test’).height(100)
width() 可以获取或者设置指定元素的宽度 获取let width = ( . t e s t ) . w i d t h ( ) p x , ('.test').width()设置,默认单位是px, (’.test’).width(100)
offset() 这个方法有两个属性,可以获取指定元素的相对于窗口的偏移量,也就是距离顶部多少距离,距离左侧多少距离 //左侧 ( . t e s t ) . o f f s e t ( ) . l e f t / / ('.test').offset().left//顶部 (’.test’).offset().top
position() 这个方法也有两个属性,获取的是相对于最近一个position属性是relative或者absolute属性的左侧和顶部距离 //左侧 ( . t e s t ) . p o s i t i o n ( ) . l e f t / / ('.test').position().left//顶部 (’.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 //绑定点击事件,也就是元素点击之后会触发第二个函数 ( . t e s t ) . o n ( c l i c k , f u n c t i o n ( ) ) / / ('.test').on('click',function(){})//多个事件 (’.test’).on(‘mouseover mouseout’,function(){})
off() 为绑定事件的对象解除绑定,可以有参数,参数是绑定的函数名,如果不传函数名,那么会将对象上绑定的所有事件一起清除 //解绑所有绑定事件 ( . t e s t ) . o f f ( ) / / t e s t f n 1 ('.test').off()//解绑指定test上的点击事件,并且是上面名为fn1的函数 (’.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])

. p o s t ( ) .post()和 .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命名空间下,比如常用的 . a j a x ( ) .ajax()方法,除去空格的 .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
}

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/105977849
今日推荐