jQuery介绍
jQuery是一个轻量级的、兼容多浏览器的JavaScript库。
jQuery使用户能够更方便地处理HTML Document、Events、实现动画效果、方便地进行Ajax交互,能够极大地简化JavaScript编程。它的宗旨就是:“Write less, do more.”
参考文档:
jQuery版本
- 1.x:兼容IE678,使用最为广泛的,官方只做BUG维护,功能不再新增。因此一般项目来说,使用1.x版本就可以了,最终版本:1.12.4 (2016年5月20日)
- 2.x:不兼容IE678,很少有人使用,官方只做BUG维护,功能不再新增。如果不考虑兼容低版本的浏览器可以使用2.x,最终版本:2.2.4 (2016年5月20日)
- 3.x:不兼容IE678,只支持最新的浏览器。需要注意的是很多老的jQuery插件不支持3.x版。目前该版本是官方主要更新维护的版本,我们学习就用3.几的就行了,工作中如果需要兼容IE678,就用1.几版本的就行,2.几版本的就别用了。
- 维护IE678是一件让人头疼的事情,一般我们都会额外加载一个CSS和JS单独处理。值得庆幸的是使用这些浏览器的人也逐步减少,PC端用户已经逐步被移动端用户所取代,如果没有特殊要求的话,一般都会选择放弃对678的支持。
jQuery对象和DOM模型互相转换
jQuery对象就是通过jQuery包装DOM对象后产生的对象。jQuery对象是 jQuery独有的。如果一个对象是 jQuery对象,那么它就可以使用jQuery里提供的方法:例如.html()%E3%80%82#card=math&code=%28%E2%80%9C%23i1%E2%80%9D%29.html%28%29%E3%80%82&id=yyKCc)(“#i1”).html()的意思是:获取id值为 i1的元素的html代码。其中 html()是jQuery里的方法。相当于DOM中的
document.getElementById("i1").innerHTML;
虽然 jQuery对象是包装 DOM对象后产生的,但是 jQuery对象无法使用 DOM对象的任何方法,同理 DOM对象也不能使用 jQuery里的方法。
有一个约定,在声明一个jQuery对象变量的时候在变量名前面加上$:
var $variable = jQuery对像
var variable = DOM对象
$variable[0] //jQuery对象转成DOM对象,通过一个jQuery对象+[0]索引零,就变成了DOM对象,就可以使用JS的代码方法了,DOM对象转换成jQuery对象:$(DOM对象),通过$符号包裹一下就可以了
拿上面那个例子举例,jQuery对象和DOM对象的使用:
$("#i1").html(); //jQuery对象可以使用jQuery的方法
$("#i1")[0].innerHTML; // DOM对象使用DOM的方法
jQuery基础语法
查找标签
基本选择器(同css)
不管找什么标签,用什么选择器,都必须要写$(“”),引号里面再写选择器,通过jQuery找到的标签对象就是一个jQuery对象,用原生JS找到的标签对象叫做DOM对象。
$("#id") // id选择器
$("tagName") // 标签选择器
$(".className") // class选择器
$("div.c1") // 标签选择器和class选择器配合使用:找到有c1 class类的div标签
$("*") // 所有元素选择器
$("#id, .className, tagName") // 组合选择器
层级选择器:(同css)
// x和y可以为任意选择器
$("x y"); // x的所有后代y(子子孙孙)
$("x > y"); // x的所有儿子y(儿子)
$("x + y"); // 找到所有紧挨在x后面的y
$("x ~ y"); // x之后所有的兄弟y
基本筛选器(选择之后进行过滤)
:first // 第一个
:last // 最后一个
:eq(index) // 索引等于index的那个元素
:even // 匹配所有索引值为偶数的元素,从 0 开始计数
:odd // 匹配所有索引值为奇数的元素,从 0 开始计数
:gt(index) // 匹配所有大于给定索引值的元素
:lt(index) // 匹配所有小于给定索引值的元素
:not(元素选择器 ) // 移除所有满足not条件的标签
:has(元素选择器) // 选取所有包含一个或多个标签在其内的标签(指的是从后代元素找)
示例:
$("div:has(h1)") // 找到所有后代中有h1标签的div标签,意思是首先找到所有div标签,把这些div标签的后代中有h1的div标签筛选出来
$("div:has(.c1)") // 找到所有后代中有c1样式类(类属性class='c1')的div标签
$("li:not(.c1)") // 找到所有不包含c1样式类的li标签
$("li:not(:has(a))") // 找到所有后代中不含a标签的li标签
属性选择器
属性选择器大多数用于input等输入标签。
// 支持的表达式(同css)
[attribute]
[attribute=value] // 属性等于
[attribute!=value] // 属性不等于
// 示例
// 测试代码如下:
用户名 <input type="text">
密码 <input type="password" name="" id="">
<input type="checkbox"> 是
// 查询语法:
$("[type=text]") // 查找type属性值为text的标签
$("[type=password]") // 查找type属性值为password的标签
$("input[type=password]") // 查找input标签的type属性值为password的标签
$("input[type!=password]") // 查找input标签的type属性值不是password的标签
表单筛选器
多用于找form表单里面出现的input标签,当然通过属性选择器找肯定也是没问题的,这样就是写着简单一些。
:text
:password
:file
:radio
:checkbox
:submit
:reset
:button
// 示例
$(":checkbox") // 找到所有的checkbox
$(":checkbox") // 只查找input中的含有checkbox的标签
// 表单对象属性
:enabled // 找到可用的标签
:disabled // 找到不可用的标签
:checked // 找到选中的input标签
:selected // 找到选中的option标签
// 其他示例
<form action=""></form>
用户名:<input type="text" disabled>
密码:<input type="password">
<input type="radio" name="sex">男
<input type="radio" name="sex">女
<input type="checkbox" name="hobby">抽烟
<input type="checkbox" name="hobby">喝酒
<select id="s1">
<option value="beijing">北京市</option>
<option value="shanghai">上海市</option>
<option selected value="guangzhou">广州市</option>
<option value="shenzhen">深圳市</option>
</select>
</form>
$("input:enabled") // 找到可用的input标签(拥有disable属性的标签不会被找到)
$("input:checked") // 找到所有被选中的input标签
$(":selected") // 找到的是被选中的option标签(这种找到的不知道是哪个option)
$(":selected").text() // 可以通过text方法来打印option的文本
筛选器方法
// 下一个:
$('#l3').next(); // 找到下一个兄弟标签
$('#l3').next().next().next(); // 链式查询,找到下一个兄弟的下一个的下一个兄弟标签
$('#l3').nextAll(); // 找到下面所有的兄弟标签
$('#l3').nextUntil('#l5'); // 直到找到id为l5的标签就结束查找,不包含它
// 上一个
$("#id").prev() // 与上面的next方法相反
$("#id").prevAll()
$("#id").prevUntil("#i2")
// 父亲元素
$("#id").parent() // 父节点
$("#id").parents() // 查找当前元素的所有的父辈元素(爷爷辈、祖先辈都找到)
$("#id").parentsUntil('body') // 查找当前元素的所有的父辈元素,直到遇到匹配的那个元素为止,这里直到body标签,不包含body标签,基本选择器都可以放到这里面使用。
// 儿子和兄弟元素
$('ul').children();
$('ul').children('#l3'); // 找到符合后面这个选择器的儿子标签
$('#l5').siblings();
$('#l5').siblings('#l3'); // 找到符合后面这个选择器的兄弟标签
// find
$('ul').find('#l3') // 类似于 $('ul #l3'),就是在ul标签中查找包含id为l3的标签
// filter过滤
$('li').filter('#l3'); // 查找li标签,然后过滤出来id为#l3的标签
// 下面的和上面提到的基本筛选器功能是一样的
.first() // 获取匹配的第一个元素
.last() // 获取匹配的最后一个元素
.not() // 从匹配元素的集合中删除与指定表达式匹配的元素 $('li').not('#l3');
.has() // 保留包含特定后代的元素,去掉那些不含有指定后代的元素。
.eq() // 索引值等于指定值的元素
操作标签
样式操作
添加/删除css样式
<!-- html 示例代码如下-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>样式操作</title>
<style>
.c1 {
background-color: blue;
width: 200px;
height: 200px;
}
.c2 {
background-color: yellow;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div class="c1" id="d1"></div>
<script src="jquery.js"></script>
<script>
</script>
</body>
</html>
操作class的js语法如下:
$('.c1').addClass('c2'); // 添加名字为c2的样式
$('.c1').removeClass('c2'); // 删除名字为c2的样式
$('.c1').hasClass('c2'); // 查看该标签是否包含名字为c2的样式
$('.c1').toggleClass('c2'); // 切换CSS类名,如果有就移除,如果没有就添加。
css样式修改
// 原生js
标签.style.color = 'red';
// jquery语法
$('.c1').css('background-color','red');
// 同时设置多个css样式
$('.c1').css({'background-color':'yellow','width':'200px'})
位置操作
// 查看位置
$('.c2').position(); //查看相对位置(查看的是距离父级或祖父级... 设置了position为relative属性的位置)
{top: 20, left: 20}
$('.c2').offset(); //查看距离浏览器窗口左上角的绝对位置
{top: 28, left: 28}
$('.c2').offset({'top':'20','left':'40'}); // 设置位置
$(window).scrollTop() //滚轮向下移动的距离
$(window).scrollLeft() //滚轮向右移动的距离
<!-- 示例页面 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>样式操作</title>
<style>
.c1 {
background-color: blue;
width: 200px;
height: 200px;
position: relative;
}
.c2 {
background-color: yellow;
width: 100px;
height: 100px;
position: absolute;
top: 20px;
left: 20px;
}
</style>
</head>
<body>
<div class="c1" id="d1">
<div class="c2">
</div>
</div>
<script src="jquery.js"></script>
<script>
</script>
</body>
</html>
下面对以上的html页面进行查看/修改等位置操作
// 查看div标签距离浏览器的位置
$(".c2").offset()
{top: 28, left: 28}
// 查看距离父级或祖父级... 设置了position为relative属性的位置
$(".c2").position()
{top: 20, left: 20}
// 设置offset值
$(".c2").offset({"top":40,"left":40})
注意,offset方法可以设置位置,position方法不可以设置值,只能查看。
jQuery绑定点击事件的写法
// 原生js绑定点击事件
// $('.c1')[0].onclick = function () { $('.c1')[0]:先通过jQuery语法查到标签,然后通过[0]转换为dom对象
// this.style.backgroundColor = 'green';
// }
// jquery绑定点击事件
$('.c1').click(function () {
$(this).css('background-color','green'); // this属于dom方法,所以需要通过$()转为jQuery方法
})
点击事件和滚动事件的示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1 {
background-color: red;
height: 100px;
width: 100px;
}
.c2 {
background-color: green;
height: 1000px;
width: 100px;
}
.c3 {
background-color: blue;
height: 1000px;
width: 100px;
}
.s1 {
position: fixed;
left: 20px;
bottom: 20px;
height: 40px;
width: 80px;
background-color: purple;
line-height: 40px;
text-align: center;
}
.s1 a {
color: white;
font-size: 14px;
text-decoration: none;
}
.hide {
display: none;
}
</style>
</head>
<body>
<!--<a name="top">这里是顶部</a>-->
<span>顶部位置</span>
<div class="c1"></div>
<button class="change-postion">走你</button>
<div class="c2"></div>
<div class="c3"></div>
<span class="s1 hide">
<!--<a href="#top">返回顶部</a>-->
<span>返回顶部</span>
</span>
<script src="jquery.js"></script>
<script>
//点击事件来改变标签位置
$('.change-postion').click(function () {
$('.c1').offset({top: 200, left: 200});
});
//滚动事件,监听滚动距离来显示或者隐藏标签
$(window).scroll(function () {
console.log($(window).scrollTop());
if ($(window).scrollTop() >= 200) {
$('.s1').removeClass('hide');
} else {
$('.s1').addClass('hide');
}
});
// 回到顶部,scrollTop设置值
$('.s1').click(function () {
$(window).scrollTop(0);
})
</script>
</body>
</html>
尺寸
// 尺寸相关方法如下(应用于盒子模型)
$('.c1').height(); //content 高度
$('.c1').width(); //content 宽度
$('.c1').innerHeight(); //content高度+padding高度
$('.c1').innerWidth(); //content宽度+padding宽度
$('.c1').outerHeight(); //content高度+padding高度 + border高度
$('.c1').outerWidth(); //content宽度+padding宽度+ border宽度
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
width: 100px;
height: 100px;
border: 2px solid red;
background-color: green;
padding: 20px 30px;
}
</style>
</head>
<body>
<div class="c1"></div>
<script src="jquery.js"></script>
</body>
</html>
页面效果如下:
jQuery查询相关尺寸:
$(".c1").height();
100
$(".c1").width();
100
$('.c1').innerHeight();
140
$('.c1').innerWidth();
160
$('.c1').outerHeight();
144
$('.c1').outerWidth();
164
文本操作
// html和text方法都是值操作,不同的是text方法只识别文本,html方法可以识别标签
html()//取得第一个匹配元素的html内容,包含标签内容
html(val)//设置所有匹配元素的html内容,识别标签,能够表现出标签的效果
text()// 取得所有匹配元素的内容,只有文本内容,没有标签
text(val)//设置所有匹配元素的内容,不识别标签,将标签作为文本插入进去
// 示例:
$('.c1').text('<h3>你好,世界</h3>'); // 设置值
$(".c1").text() // 查看值
"<h3>你好,世界</h3>"
$('.c1').html('<h3>你好,世界</h3>'); // 使用html方法设置值
// 用两种方法分别查看值
$(".c1").html()
"<h3>你好,世界</h3>"
$(".c1").text()
"你好,世界"
值操作
// 获取值
input type='text'的标签--$('#username').val();
input type='radio'标签获取被选中的标签的值 --- $(':radio:checked').val();
input type='checkbox'标签获取被选中的标签的值 --- 直接$(':checkbox:checked').val();是不行的,需要循环取值
var d = $(':checkbox:checked');
for (var i=0;i<d.length;i++){
console.log(d.eq(i).val());
}
单选select --- $('#city').val();
多选select --- $('#author').val(); // ["2", "3"]
设置值
input type='text'的标签 --- $('#username').val('李杰');
input type='radio'标签 --- $('[name="sex"]').val(['3']);
如果 $('[name="sex"]').val('3'),所有标签的值都变成了'3';
input type='checkbox'设置值 --- $('[name="hobby"]').val(['2','3'])
单选select --- $('#city').val('1'); option value='1'
多选select --- $('#author').val(['2','3'])
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
用户名:<input type="text" id="username">
</div>
<div>
选择性别 :
<input type="radio" name="sex" value="1">男
<input type="radio" name="sex" value="2">女
</div>
<div>
选择爱好:
<input type="checkbox" name="hobby" value="1">抽烟
<input type="checkbox" name="hobby" value="2">喝酒
<input type="checkbox" name="hobby" value="3">烫头
<input type="checkbox" name="hobby" value="4">洗脚
</div>
<div>
城市:
<select name="" id="city">
<option value="1">湖北孝感</option>
<option value="2">河北廊坊</option>
<option value="3">山东烟台</option>
<option value="4">黑龙江哈尔滨</option>
</select>
</div>
<div>
<select name="" id="author" multiple>
<option value="1">张三</option>
<option value="2">赵四</option>
<option value="3">王五</option>
</select>
</div>
<script src="jquery.js"></script>
</body>
</html>
页面效果如下:
// 获取值
$('#username').val() // input标签获取值
"吕建钊"
$(':radio:checked').val() // 获取type="radio" 的标签选中的值(打印的是标签中value的值)
1
// 获取复选框被选中的值,直接$(":checkbox:checked") 获取到的是一个数组,还需要循环取值
var d = $(":checkbox:checked")
for (var i = 0; i < d.length; i++) {
console.log(d.eq(i).val())
}
1
2
$("#city").val() // 单选下拉框获取值
"1"
$("#author").val() // 多选下拉框获取值,返回的是一个数组
(2) ["1", "2"]
// 设置值
$('#username').val("法外狂徒张三") // input标签设置新值
$('[name="sex"]').val(['2']); /*设置单选框的值,一定要按照格式,否则会改掉所有标签的值。
如果 $('[name="sex"]').val('3'),所有标签的值都变成了'3';
*/
$('[name="hobby"]').val(['2','4']); // 设置复选框的值
$('#city').val('3') // 设置单选下拉框的值
$('#author').val([['1'],'3']) // 设置多选选下拉框的值
属性操作
attr(attrName) // 返回第一个匹配元素的属性值
attr(attrName, attrValue) // 为所有匹配元素设置一个属性值
attr({k1: v1, k2:v2}) // 为所有匹配元素设置多个属性值
removeAttr(attrName) // 从每一个匹配的元素中删除一个属性
// 示例:
// 设置单个属性
$('.c1').attr('xx','oo');
// 设置多个属性
$('.c1').attr({'age':'18','sex':'alex'});
// 查看属性
$('.c1').attr('属性名');
$('.c1').attr('xx');
// 删除属性
$('.c1').removeAttr('xx');
// prop -- 针对的是checked\selected\disabled..
// 查看标签是否有checked属性,也就是是否被选中
$(':checked').attr('checked'); //checked -- undefined
$(':checked').prop('checked'); //true -- false
// 通过设置属性的方式来设置是否选中:
$(':radio').eq(2).prop('checked',true); // 选中此选项 true和false不能加引号
$(':radio').eq(2).prop('checked',false); // 取消选中此选项
/*
简单总结:
1.对于标签上有的能看到的属性和自定义属性都用attr
2.对于返回布尔值的比如checkbox、radio和option的是否被选中或者设置其被选中与取消选中都用prop。
具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他的使用 attr()
*/
文档处理
// 添加到指定元素内部的后面
$(A).append(B) // 把B追加到A
$(A).appendTo(B) // 把A追加到B
$('#d1').append('<a href="http://www.jd.com">京东</a>'); // 添加字符串照样能识别标签
// 添加到指定元素内部的前面
$(A).prepend(B) // 把B前置到A
$(A).prependTo(B) // 把A前置到B
// 添加到指定元素外部的后面
$(A).after(B) // 把B放到A的后面
$(A).insertAfter(B) // 把A放到B的后面
// 添加到指定元素外部的前面
$(A).before(B) // 把B放到A的前面
$(A).insertBefore(B) // 把A放到B的前面
// 移除和清空元素
remove() // 从DOM中删除所有匹配的元素。
empty() // 删除匹配的元素集合中所有的子节点,包括文本被全部删除,但是匹配的元素还在
// 替换
replaceWith()
replaceAll()
// clone()克隆
<button class="btn">屠龙宝刀,点击就送!</button>
$('.btn').click(function () {
// var a = $(this).clone(); //克隆标签
var a = $(this).clone(true); //连带事件一起克隆
$(this).after(a);
})
示例html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.d1 {
border: 1px solid red;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div class="d1">
<span id="sp">你好span</span>
</div>
<a href="http://www.baidu.com" id="bd">百度</a>
<script src="jquery.js">
</script>
</body>
</html>
文档操作示例如下:
// 添加到指定元素内部的后面
$('.d1').append($("#bd")) // 把$("#bd")追加到$('.d1')内部的后面
$('#bd').appendTo($(".d1")) // 把$("#bd")追加到$('.d1')内部的后面
$('.d1').append("<a href=http://jd.com>京东</a>") // 把新建的a标签插入到div标签内部的后面
// 添加到指定元素内部的前面
$(".d1").prepend($('#bd')) // 把$("#bd")插入到$('.d1')内部的前面
$("#bd").prependTo($('.d1')) // 把$("#bd")插入到$('.d1')内部的前面
// 添加到指定元素外部的后面
var a1=document.createElement('a'); // 创建一个a标签并设置相关属性
a1.href="https://www.taobao.com/"
a1.innerText="淘宝"
$('.d1').after(a1) // 把创建的a标签放到$('.d1')标签的后面
$('.d1').insertAfter(a1) // 把$('.d1')标签放到a标签的后面
// 添加到指定元素外部的前面
$("#bd").insertBefore($(".d1")) // 把$("#bd")放到$(".d1")的前面
$("#bd").before($(".d1")) // 把$(".d1")放到$("#bd")的前面
// 移除和清空元素
$('.d1').remove() // 移除整个$('.d1')标签
$(".d1").empty(); // 清空$('.d1')标签内的所有内容
// 替换
var a1=document.createElement('a'); // 创建一个a标签并设置相关属性
a1.href="https://www.taobao.com/"
a1.innerText="淘宝"
$('span').replaceWith(a1) // 将span标签替换为a1标签
$(a1).replaceAll('span') // 将span标签替换为a1标签
克隆示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="but">屠龙宝刀,点击就送!</button>
<script src="jquery.js"></script>
<script>
$('.but').click(function () {
// var a = $(this).clone(); clone不带任何参数,则只克隆标签内容,不克隆绑定的事件
var a = $(this).clone(true); // clone传入true,则连带事件一起克隆
$(this).after(a);
})
</script>
</body>
</html>
事件
jQuery常用事件
事件 | 作用 |
---|---|
click(function(){…}) | 当用户点击某个对象时调用的事件句柄 |
hover(function(){…}) | hover就是鼠标放上去(mouseenter)和离开(mouseout)的复合写法 |
blur(function(){…}) | 元素失去焦点。 |
focus(function(){…}) | 元素获得焦点。 |
change(function(){…}) | 域的内容被改变。(一般用于select标签做联动效果) |
keydown(function(){…}) | 某个键盘按键被按下。 |
keyup(function(){…}) | 某个键盘按键被松开。 |
mouseover | 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。 |
mouseenter | 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。 |
input | 实时获取input、textarea等标签中的值,应用场景比如一些搜索引擎的关键字联想等,和change事件有相似之处,不同是在于input事件是只要你的元素的内容发生了改变,就会触发事件 |
事件绑定方式
<script src="jquery.js"></script>
<script>
//方式1
// $('#d1').click(function () {
// $(this).css({'background-color':'green'});
// });
//方式2
$('#d1').on('click',function () {
$(this).css({'background-color':'green'});
})
</script>
上面的几个常用事件,在博文中的练习题大纲中有示例。
事件冒泡与事件委托
事件冒泡
所谓事件冒泡,就是当一个元素上的事件被触发的时候,同样的事件将会在那个元素的所有祖先元素中被触发。 这一过程被称为事件冒泡;使用事件代理,我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。
先来说说事件冒泡的现象以及如何防止事件冒泡:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.d1 {
width: 500px;
height: 500px;
background-color: blue;
}
.d2 {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div id="d1" class="d1">
<div id="d2" class="d2">
</div>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$('.d1').click(function () {
alert('这是父级标签')
});
$('.d2').click(function () {
alert('这是子标签');
})
</script>
</body>
</html>
上面的代码中,我点击父级div标签就想触发父级的事件,点击子级的div标签只想触发子级的事件,可是当我们真正点击时会发现,触发子级事件的同时,也会触发父级的事件,那么如何避免呢?有以下两种方式:
// 方式一:
$('.d2').click(function (e) {
alert('这是子标签');
return false; // 在子级标签事件的后面加上这一句即可
})
// 方式二
$('.d2').click(function (e) { //这个参数e(只是个形参,写evt或者event名字的也很多)表示当前事件本身,这个事件也是一个对象
alert('这是子标签');
e.stopPropagation() // 或者使用这个方法
})
事件委托
什么是事件委托?
事件委托也称之为事件代理(Event Delegation)。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
举个通俗的例子:比如一个宿舍的同学同时快递到了,一种方法就是他们一个个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一 一分发给每个宿舍同学;
在这里,取快递就是一个事件,每个同学指的是需要响应事件的 DOM 元素,而出去统一领取快递的宿舍长就是代理的元素,所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个。
一个事件触发后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段:
- (1)捕获阶段:从window对象传导到目标节点(上层传到底层)称为“捕获阶段”(capture phase),捕获阶段不会响应任何事件;
- (2)目标阶段:在目标节点上触发,称为“目标阶段”
- (3)冒泡阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层。
事件委托的优点:
【1】可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件就非常棒
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
如上面代码所示,如果给每个li列表项都绑定一个函数,那对内存的消耗是非常大的,因此较好的解决办法就是将li元素的点击事件绑定到它的父元素ul身上,执行事件的时候再去匹配判断目标元素。
【2】可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
假设上述的例子中列表项li就几个,我们给每个列表项都绑定了事件;
在很多时候,我们需要通过 AJAX 或者用户操作动态的增加或者删除列表项li元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的;所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。
使用事件委托注意事项:使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。
下面是事件委托的一个简单例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="d1">
<button>爱的魔力转圈圈</button>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$('button').on('click', function () {
// 当点击按钮时创建一个button按钮并追加到指定div标签的后面
var ele = document.createElement("button");
ele.textContent = '爱的魔力转圈圈';
$('#d1').append(ele)
})
</script>
</body>
</html>
上面的代码并不涉及事件委托,但是它存在一个问题,就是新增的按钮不会绑定事件(需要手动添加事件或者使用clone来克隆按钮,而不是手动创建按钮并添加),那么如果使用事件委托的话,就可以将事件委托给父级div标签,这样就可以了,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="d1">
<button>爱的魔力转圈圈</button>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
// 将'button' 选择器选中的标签的点击事件委托给了$('#d1');
$('#d1').on('click', 'button', function () {
var ele = document.createElement("button");
ele.textContent = '爱的魔力转圈圈';
console.log($(this)); // this对象还是我们点击的那个button按钮
$('#d1').append(ele)
})
</script>
</body>
</html>
上面代码就实现了,新追加的button标签,都可以触发事件。
注意:
像click、keydown等DOM中定义的事件,我们都可以使用.on()
方法来绑定事件,但是hover
这种jQuery中定义的事件就不能用.on()
方法来绑定了。
想使用事件委托的方式绑定hover事件处理函数,可以参照如下代码分两步绑定事件:
$('ul').on('mouseenter', 'li', function() {//绑定鼠标进入事件
$(this).addClass('hover');
});
$('ul').on('mouseleave', 'li', function() {//绑定鼠标划出事件
$(this).removeClass('hover');
});
页面载入
当DOM载入就绪可以查询及操纵时绑定一个要执行的函数。这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度。
将js代码写到head标签和写到body标签下面的作用是不同的,写在head标签里面的话,如果你写了操作某个标签的内容的话,那个标签还没加载出来,先加载了你的js代码,就找不到这个标签,所以不会生效,所以写在body标签最下面是一种解决办法,还有一种办法就是window.onload=function(){js的代码},等页面上所有的元素都加载完,再执行这里面的js代码,但是这个window.onload有个缺点,这个缺点就是这个操作时给window.onload赋值,如果你自己写了两个js文件,每个js文件中都有一个window.onload的话,那么后引入的文件会把前面引入的文件的window.onload里面的js代码全部覆盖掉,那么第一个文件的js代码就失去了效果,还有一个问题就是,window.onload会等到页面上的文档、图片、视频等所有资源都加载完才执行里面的js代码,导致有些效果的加载比较慢,所以我们使用下面的写法,不存在覆盖问题,而且只要文档加载完就触发,不需要等着一些图片啊视频啊什么的,加载js效果的速度快。
两种写法:
// 写法一
$(document).ready(function(){
// 在这里写你的JS代码...
})
// 简写:
$(function(){
// 你在这里写你的代码
})
注意:如果你其他js文件中用到了jQuery,那么需要在加载其他js文件之前先加载jQuery。
动画效果(了解即可)
// 基本
show([s,[e],[fn]]) $('.c1').show() //show(5000),就是5秒之后显示出来这个标签,并且有一个动画效果,(搞个img图片看看效果),后面两个参数先不用管
hide([s,[e],[fn]]) $('.c1').hide() // hide(5000),就是5秒之后隐藏这个标签,同样有动画效果
toggle([s],[e],[fn]) //这个toggle的意思就是你原来是什么效果,我就反着来
slideDown([s],[e],[fn]) // 从上往下滑动的显示出来
//使用的时候别忘了给标签设置一个高度和宽度,其实就是控制你的标签高度,如果你写$('#di').slideUp(5000);意思就是5秒内把你的高度变为0
//还有如果你直接操作的是img标签和操作img标签的父级标签,两个的效果是不同的
slideUp([s,[e],[fn]])
slideToggle([s],[e],[fn]) //这个slideToggle的意思就是你原来是什么效果,我就反着来
// 淡入淡出(控制透明度)
fadeIn([s],[e],[fn]) // 慢慢显示出来
fadeOut([s],[e],[fn]) // 慢慢隐藏起来
fadeTo([[s],o,[e],[fn]]) // o参数是透明度,0-1的区间,意思是淡入或者淡出到一个多大的透明度,比如:$('#d1').fadeTo(3000,0.3)
fadeToggle([s,[e],[fn]]) //这个fadeToggle的意思就是你原来是什么效果,我就反着来
下面就是一个示例页面,可以用浏览器打开后,在控制台来做一些动画效果,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#d1 {
width: 300px;
height: 300px;
background-color: red;
display: none;
}
</style>
</head>
<body>
<div id="d1">
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</body>
</html>
each循环和data方法
each循环
.each() 方法用来迭代jQuery对象中的每一个DOM元素。每次回调函数执行时,会传递当前循环次数作为参数(从0开始计数)。由于回调函数是在当前DOM元素为上下文的语境中触发的,所以关键字 this 总是指向这个元素。
下面是循环一个无序列表中的值,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>11</li>
<li>22</li>
<li>33</li>
<li>44</li>
<li>55</li>
</ul>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</body>
</html>
如果想要循环取出来上面的无需列表值,可以通过如下方法:
$('li').each(function(){
console.log(this); // this指的是当前循环的那个标签对象,以后循环标签的时候,就不用自己写for循环了,用each就行了
})
//k 是元素的索引位置
$('li').each(function (k, v) {
console.log(k, v.text())
})
当然,除了上面的那种取值方法,也可以用这个方法循环取值一个列表,如下:
var list_1 = [11, 22, 33, 44, 55, 6, 7, 8]; // 定义一个列表
$.each(list_1, function (i, v) {
// 如果索引位置为4,就终止循环
if (i === 4) {
return false;
}
console.log(i, v);
})
data方法
任意jQuery对象都有data方法,可以保存任意值,可以用来代替全局变量
在匹配的元素集合中的所有元素上存储任意相关数据或返回匹配的元素集合中的第一个元素的给定名称的数据存储的值。
.data(key, value): 设置值
在匹配的元素上存储任意相关数据。
$('ul').data("k",500) // 给所有ul标签都保存一个名为k,值为100
取值,没有的话返回undefined
返回匹配的元素集合中的第一个元素的给定名称的数据存储的值—通过 .data(name, value)或 HTML5 data-*属性设置。
$('ul').data("k") //返回第一个ul标签中保存的"k"的值
.removeData(key)
移除存放在元素上的数据,不加key参数表示移除所有保存的数据。
$('ul').removeData("k") // //移除元素上存放k对应的数据
练习题
简单的用户名密码合法性
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>文本操作之登录验证</title>
<style>
.sp {
color: red;
}
</style>
</head>
<body>
<form action="">
<div id="d1">
<label for="username">用户名: </label>
<input id="username" type="text" name="username">
<span class="sp"></span>
</div>
<div id="d2">
<label for="password">密码: </label>
<input id="password" type="password" name="password">
<span class="sp"></span>
</div>
<button>提交</button>
</form>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$('#username').blur(function () {
if ($(this).val().length === 0) {
$('#d1 span').text('用户名不能为空')
} else {
$(this).next().text('')
}
})
$('#password').blur(function () {
if ($(this).val().length === 0) {
$(this).next().text('密码不能为空')
} else {
$(this).next().text('')
}
})
</script>
</body>
</html>
全选反选取消
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="all">全选</button>
<button id="reverse">反选</button>
<button id="cancel">取消</button>
<table border="1" cellpadding="1" cellspacing="2">
<thead>
<tr>
<th>###</th>
<th>姓名</th>
<th>爱好</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" value="1"></td>
<td>张三</td>
<td>打篮球</td>
</tr>
<tr>
<td><input type="checkbox" value="2"></td>
<td>尼古拉斯.赵四</td>
<td>抽烟喝酒烫头</td>
</tr>
<tr>
<td><input type="checkbox" value="3"></td>
<td>王五</td>
<td>打羽毛球</td>
</tr>
</tbody>
</table>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
// 全选
$("#all").click(function () {
$(':checkbox').prop('checked', true)
});
// 反选
$("#reverse").click(function () {
var $checkbox = $(':checkbox');
for (var i = 0; i < $checkbox.length; i++) {
var l1 = $($checkbox[i]);
var status = l1.prop('checked');
$($checkbox[i]).prop('checked', !status)
}
})
/*
方法2. 先用变量把标签原来的状态保存下来
var $unchecked = $("input:not(:checked)");
var $checked = $("input:checked");
$unchecked.prop('checked', true);
$checked.prop('checked', false);
*/
// 取消选择
$("#cancel").click(function () {
$(':checkbox').prop('checked', false)
});
</script>
</body>
</html>
爱好登录表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.cover {
background-color: rgba(0, 0, 0, 0.3); /*设置当添加数据时,将背景颜色改为黑色,0.3为透明度*/
top: 0;
left: 0;
right: 0;
bottom: 0;
position: fixed; /*生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。*/
z-index: 99; /*设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面*/
}
.modal { /*设置新增记录时的输入框*/
width: 300px;
height: 200px;
background-color: white;
position: absolute; /*将对象从文档流中拖出,使用left,right,top,bottom等属性进行绝对定位。*/
top: 50%;
left: 50%;
/*margin-xxxx:设置外边距*/
margin-top: -100px;
margin-left: -150px;
z-index: 100; /*设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面*/
text-align: center; /*文本居中*/
}
.hide {
display: none; /*隐藏div框*/
}
</style>
</head>
<body>
<!--初始化表格-->
<button id="add">新增</button>
<table border="1">
<thead>
<tr>
<th>#</th>
<th>姓名</th>
<th>爱好</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>张三</td>
<td>开车</td>
<td>
<button class="fire">开除</button>
<button class="edit">编辑</button>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>赵四</td>
<td>打架</td>
<td>
<button class="fire">开除</button>
<button class="edit">编辑</button>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>王五</td>
<td>泡脚</td>
<td>
<button class="fire">开除</button>
<button class="edit">编辑</button>
</td>
</tr>
</tbody>
</table>
<!--灰色背景,默认不显示-->
<div class="cover hide">
</div>
<!--新增记录的输入框,默认不显示(点击“新增”按钮后显示)-->
<div class="modal hide">
<div>
<label>姓名:
<input type="text" id="name">
</label>
</div>
<div>
<label>爱好:
<input type="text" id="hobby">
</label>
</div>
<div>
<button id="submit">提交</button>
<button id="cancel">取消</button>
</div>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
var editTd; // 此变量用于接收点击编辑按钮的那行tr标签(用于更新提交编辑后的更新记录操作)
var flag; // 此变量用于接收是编辑操作还是添加操作(用于在点击提交按钮时,判断是新增记录,还是修改记录)
// 隐藏函数
function hide() {
$('.modal,.cover').addClass('hide')
}
// “添加”按钮功能
$('#add').click(function () {
flag = 1; // 1、设置flag为1,表示添加操作
// 2、清空两个input输入框
$('#name').val('');
$('#hobby').val('');
$('.modal,.cover').removeClass('hide'); // 3、移除隐藏属性,显示出来input标签
});
// “编辑”按钮功能
$('.edit').click(function () {
flag = 2; // 1、设置flag为2,表示为编辑操作
editTd = $(this).parent(); // 2、获取当前操作行的标签,也就是当前点击的编辑按钮所在的td标签
// 3、获取当前行现在的用户名与爱好
var username = editTd.prev().prev().text();
var hobby = editTd.prev().text();
// 4、将获取的原本的用户名及爱好赋值给两个input框
$('#name').val(username);
$('#hobby').val(hobby);
// 5、移除隐藏功能,将input标签显示出来
$('.modal,.cover').removeClass('hide');
});
// “提交”按钮功能
$('#submit').click(function () {
// 1、获取两个input输入框中的值
var username = $('#name').val();
var hobby = $('#hobby').val();
if (flag === 1) { // 2、如果flag为1,则表示为 新增 操作,进入新增记录模块中
// 2.1、拼接要插入的记录
var newTr = '<tr><td><input type="checkbox"></td><td>' + username + '</td><td>' + hobby + '</td><td><button class="fire">开除</button><button class="edit">编辑</button></td></tr>';
// 2.2、将拼接的记录插入到表格中
$('tbody').append(newTr);
} else { // 3、如果flag为2,则表示为 更新 操作,进入更新记录模块中
// 3.1 直接更新当前记录,editTd是在点击“更新”按钮时,赋值的(editTr = $(this).parent();)
editTd.prev().prev().text(username);
editTd.prev().text(hobby);
}
hide();
});
// “取消”按钮功能
$('#cancel').click(function () {
hide();
});
// “开除”按钮功能
$('tbody').on('click', '.fire', function () {
$(this).parent().parent().remove();
});
</script>
</body>
</html>
事件相关示例
hover示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.sp {
background-color: grey;
}
</style>
</head>
<body>
<p class="sp">这是hover事件的示例</p>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$(".sp").hover(function () { // 第一个匿名函数是当鼠标停留在元素上的效果
$("p").css({'background-color': 'yellow'});
}, function () { // 第二个匿名函数是当鼠标离开元素上的效果
$("p").css({'background-color': 'grey'});
})
</script>
</body>
</html>
mouseover 和 mouseenter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.d1 {
padding: 20px;
width: 40%;
background-color: darkgrey;
float: left;
}
.d2 {
padding: 20px;
width: 40%;
background-color: darkgrey;
float: right;
}
h2 {
background-color: white;
}
</style>
</head>
<body>
<div id="over" class="d1">
<h2>这是触发的 mouseover 事件:<span></span></h2>
</div>
<div id="enter" class="d2">
<h2>这是触发的 mouseenter 事件: <span></span></h2>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
var x = 0
var y = 1
$('.d1').mouseover(function () {
$('.d1 span').text(x += 1)
})
$('.d2').mouseenter(function () {
$('.d2 span').text(y += 1)
})
</script>
</body>
</html>
keydown和keyup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.d1 {
padding: 20px;
width: 40%;
background-color: darkgrey;
float: left;
}
.d2 {
padding: 20px;
width: 40%;
background-color: darkgrey;
float: right;
}
h2 {
background-color: white;
}
</style>
</head>
<body>
<div id="d1" class="d1">
<h2>您按下的键盘代码为:<span></span></h2>
</div>
<div id="d2" class="d2">
<h2>您抬起的键盘代码为:<span></span></h2>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
// keydown 的事件
$(window).keydown(function (e) { // 这里的e为固定写法,一般写为e或者event,表示事件
$('#d1 span').text(e.keyCode) // e.keyCode可以获取键盘代码
});
// keyup 的事件
$(window).keyup(function (e) {
$('#d2 span').text(e.keyCode)
})
</script>
</body>
</html>
input事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<br>
<label>
请输入内容:<input type="text">
</label>
</br>
您输入的实时内容:<span id="sp"></span>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$('[type=text]').on('input', function () {
$('#sp').text($(this).val())
})
</script>
</body>
</html>
change和keydown、keyup事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>#</th>
<th>姓名</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>Egon</td>
<td>
<select>
<option value="1">上线</option>
<option value="2">下线</option>
<option value="3">停职</option>
</select>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>Alex</td>
<td>
<select>
<option value="1">上线</option>
<option value="2">下线</option>
<option value="3">停职</option>
</select>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>Yuan</td>
<td>
<select>
<option value="1">上线</option>
<option value="2">下线</option>
<option value="3">停职</option>
</select>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>EvaJ</td>
<td>
<select>
<option value="1">上线</option>
<option value="2">下线</option>
<option value="3">停职</option>
</select>
</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>Gold</td>
<td>
<select>
<option value="1">上线</option>
<option value="2">下线</option>
<option value="3">停职</option>
</select>
</td>
</tr>
</tbody>
</table>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
var flag = false;
$(window).keydown(function (e) {
if (e.keyCode === 16) {
flag = true;
}
});
$(window).keyup(function (e) {
if (e.keyCode === 16) {
flag = false;
}
});
$('select').change(function (e) {
var isChecked = $(this).parent().siblings().first().find(":checkbox").prop("checked");
console.log($(this).val())
if (flag && isChecked) {
// 当按着shift键时,flag为true,松开flag键时,flag为false进入批量编辑模式
// 1. 取到当前select选中的值
var value = $(this).val(); //别忘了this是个dom对象,要用$(this)包裹起来变成jQuery对象
// 2. 给其他被选中行的select设置成和我一样的值
// 2.1 找到那些被选中行的select,被选中的行就是$('input:checked')
var $select = $("input:checked").parent().parent().find("select") //一般jQuery中的变量名,我们在变量名前面加一个$符号区分一下
//var $select = $('tr:has(input:checked)').find('select') 这个也可以,选择某些标签的方法有很多
// 2.2 给选中的select赋值
$select.val(value);
}
});
</script>
</body>
</html>