没有太晚的开始,不如就从今天行动。总有一天,那个一点一点可见的未来,会在你心里,也在你的脚下慢慢清透。生活,从不亏待每一个努力向上的人。
第二期主要内容
- 查找
- 修改
- 按节点间关系查找
- 添加/删除/替换/克隆
- 事件绑定
一. 查找: jQuery新增选择器
-
内容过滤选择器:
(1). 什么是: 根据元素的内容中包含的关键词来匹配元素
(2). 何时: 如果用其它选择器很难区分元素时,就可以尝试用元素的内容不同来选择元素
(3). 包含: 4种:
a. :contains(关键词) 匹配元素内容中包含指定"关键词"的元素
b. :has(选择器) 匹配子元素中包含符合选择器要求的元素 的父元素 根据孩子特征,选爹
c. :parent 匹配所有内容不为空的元素
d. :empty 匹配内容为空的元素
强调: 空元素: 连空字符内容都不能有!(4). 示例: 使用内容过滤选择器选择指定元素
<!DOCTYPE html>
jQuery中的选择器——内容过滤选择器
<button>提交订单</button>
<button>Submit注册信息</button>
<button>马上提交</button>
<button>清空重填</button>
<hr />
<div class="alert" id="alert1">
第一个警告框
</div>
<div class="alert" id="alert2">
<span class="close">×</span>
第一个警告框
</div>
<div class="alert" style="height:30px"></div>
```
-
可见性过滤:
(1). 什么是: 根据元素是否可见来选择元素
(2). 包括:
a. :visible 专门匹配可见的元素
b. :hidden 专门匹配不可见的元素
坑: 只能选择display:none和type="hidden"隐藏的元素 无法选择visibility:hidden和opacity:0的元素(4). 示例: 使用:hidden查找隐藏的元素
<!DOCTYPE html>
可见性选择器
<div id="d1" style="display: none">lorem</div>
<div id="d2" style="visibility: hidden">lorem</div>
<div id="d3" style="opacity: 0">lorem</div>
<input id="d4" type="hidden" name="aa" value="bb" />
```
-
表单元素过滤选择器:
(1). :input 专门选择所有表单元素(input 、button、textarea 、select)
vs input 只是一个普通的元素选择器,只能选择input元素。不能选择其他类型的表单元素(2). 问题: input元素就有很多种类,如何精确的只选择其中一种种类的input呢?
(3). 解决: 其实,input元素的每种type值,都对应着一个专门的选择器,比如:
a. :text 专门选择
<input type="text"b. :password 专门选择
<input type="password"c. :radio 专门选择
<input type="radio"... ...
(4). 示例: 点同意,启用表单元素;不同意,就禁用表单元素
<!DOCTYPE html>
<html>
<head>
<title>.....</title>
<meta charset="utf-8" />
<style>
</style>
</head>
<body>
<form>
用户名:<input disabled></br>
密码:<input type="password" disabled></br>
<input type="checkbox">我同意本站的使用条款<br>
<input type="submit" value="提交注册信息" disabled />
</form>
<script src="js/jquery-1.11.3.js"></script>
<script>
//DOM 4步
//1. 查找触发事件的元素
//本例中: 用户点type=checkbox的复选框触发启用禁用状态的改变
//应该查找type=checkbox的一个复选框
$(":checkbox")
//2. 绑定事件处理函数
//本例中:单击复选框触发变化
.click(function(){
//3. 查找要修改的元素
//本例中: 点了复选框要修改除当前复选框之外其余所有表单元素
var $others=$(":input:not(:checkbox)")
//4. 修改元素
//获得当前checkbox的选中状态
//错误: jQuery是函数库,不能用属性方式
//var checked=$(this).checked;
// 当前复选框 获取 checked属性的值
var checked=$(this).prop("checked");
//因为checked属性值只是一个bool值,不是jQuery家子对象
//所以变量名不加$
//如果checkbox是选中的
if(checked==true){
//其它表单元素启用
//修改其他表单元素的disabled属性值为false
$others.prop("disabled",false);
}else{//否则如果checkbox是未选中的
//其它表单元素禁用
//修改其他表单元素的disabled属性值为true
$others.prop("disabled",true);
}
//基础好的同学,必须改为1句话!
//如果选中(checked为true),则其它元素启用(disabled为false)
//否则如果未选中(checked为false),则其它元素禁用(disabled为true)
//所以,只要让其他元素的disabled值和checked的值相反就行!不用三目!
})
</script>
</body>
</html>
运行结果:
二. 修改: 3种东西
- 内容: 3种:
修改元素的内容(有扩展)
(1). 原始的HTML内容:
a. DOM中: 元素.innerHTML
b. jq中: $元素.html("新内容")
(2). 纯文本内容:
a. DOM中: 元素.textContent
b. jq中: $元素.text("新内容")
(3). 表单元素的值:
a. DOM中: 元素.value
b. jq中: $元素.val("新值")
(4). 示例: 通过修改元素内容,实现表单验证
<!DOCTYPE html>
<html>
<head>
<title> new document </title>
<meta charset="utf-8">
</head>
<body>
<h1>操作元素的内容和值</h1>
<form action="">
用户名:<input name="uname">
<span></span><br>
密码:<input type="password" name="upwd">
<span></span><br>
<input type="submit" value="提交注册信息">
</form>
<script src="js/jquery-1.11.3.js"></script>
<script>
//正确时,使用图片:"<img src='img/ok.png'>"
//姓名错误时: "<img src='img/err.png'>用户名必须介于3~9位之间!"
//密码错误时: "<img src='img/err.png'>密码必须介于6~8位之间!"
//DOM 4步
//1. 查找触发事件的元素
//本例中: 当姓名文本框失去焦点时,触发验证和变化
//应该找文本框:
$(":text")
//2. 绑定事件处理函数
//本例中: 失去焦点触发验证和变化
.blur(function(){
var $txt=$(this);
//3. 查找要修改的元素
//本例中: 不管验证通过还是未通过,都要修改文本框旁边的下一个span
var $span=$txt.next();
//4. 修改元素
//获得文本框中内容去掉空字符后的长度
var length=$txt.val().trim().length;
//如果长度介于3~9位字符之间,就验证通过
if(length>=3&&length<=9){
//就设置span的内容为<img src='img/ok.png'>
$span.html(`<img src='img/ok.png'>`)
}else{//否则如果验证不通过
//就设置span的内容为<img src='img/err.png'>用户名必须介于3~9位之间!
$span.html(`<img src='img/err.png'>用户名必须介于3~9位之间!`);
}
});
//自己模仿我的姓名文本框,制作密码框验证
</script>
</body>
</html>
运行结果:
-
属性: 3种:
(1). 字符串类型的HTML标准属性:
a. DOM中: 2种:
1). 核心DOM 4个函数: 元素.getAttribute() setAttribute() ... 2). HTML DOM: 元素.属性名b. jq中: 2种:
1). $元素.attr("属性名", "新值") 代替元素.getAttribute() setAttribute() ... attribute指 HTML中开始标签中的属性 一个函数两用 2).问题: jQuery是函数库,不能用".属性名"方式访问 解决: jQuery中封装了一个新函数.prop("属性名", "新值"),专门代替".属性名"方式来获取或修改元素的属性值 property 指 内存中元素对象上的属性 一个函数两用(2). bool类型的HTML标准属性
a. DOM中: 元素.属性名, 不能用核心DOM getAttribute()和setAttribute()
d. 如何: $元素.prop("属性名", bool) 代替".属性名"
c. 因为在DOM中不能用getAttribute()和setAttribute(),所以在jq中也不能用attr()
(3). 自定义扩展属性:
a. DOM中: 2种:
1). 核心DOM4个函数: 元素.getAttribute() 元素.setAttribute() 2). HTML5: 元素.dataset.自定义属性名b. jq中: 1种: $元素.attr() 代替 元素.getAttribute() 元素.setAttribute()
c. 强调: 因为自定义属性在DOM中就不能用".属性名"方式访问,所以jq中自然也就不能用.prop()来访问!因为prop()代替的就是".属性名"
(4). 示例: 点击图片切换下一张
<!DOCTYPE html>
<html>
<head>
<title> new document </title>
<meta charset="utf-8">
</head>
<body>
<h1>操作元素的属性</h1>
<img src="img/1.jpg" alt="1">
<script src="js/jquery-1.11.3.js"></script>
<script>
//单击图片,切换下一张
//DOM 4步
//1. 查找触发事件的元素
//本例中: 用户点img触发变化
$("img")
//2. 绑定事件处理函数
//本例中: 单击触发变化
.click(function(){
//3. 查找要修改的元素
//本例中: 就是要修改当前img自己
var $img=$(this);
//4. 修改元素
//本例中:
//先获取当前img中alt属性的值转为整数
var i=parseInt($img.attr("alt"));
// .prop("alt")
if(i<4){//如果alt值<4,则alt+1
i++;
}else{//否则如果alt值==4,则alt=1
i=1;
}
//最后将alt的值拼成新的src路径,设置到img的src属性上,同时,将alt值再放回img的alt属性中,为下次点击做准备
//$img.attr("src",`img/${i}.jpg`);
// .prop()
//$img.attr("alt",i);
// .prop()
$img.attr({ src:`img/${i}.jpg`, alt:i })
// .prop()
})
</script>
</body>
</html>
运行结果:
(5). 示例: 点击小图片,切换大图片
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
text-align: center;
}
</style>
</head>
<body>
<img src="img/1.jpg" data-target="img/1-l.jpg" class="my-small">
<img src="img/2.jpg" data-target="img/2-l.jpg" class="my-small">
<img src="img/3.jpg" data-target="img/3-l.jpg" class="my-small">
<img src="img/4.jpg" data-target="img/4-l.jpg" class="my-small">
<hr />
<img src="img/1-l.jpg" class="my-big">
<script src="js/jquery-1.11.3.js"></script>
<script>
//点击小图片,下方my-big中显示大图片
//DOM 4步
//1. 查找触发事件的元素
//本例中: 用户点class为my-small的img元素触发变化
$(".my-small")
//2. 绑定事件处理函数
//本例中: 单击触发变化
.click(function(){
//3. 查找要修改的元素
//本例中: 要修改class为my-big的img
$(".my-big")
//4. 修改元素
//本例中: 要修改my-big的src属性为当前点击的小图片上的data-target属性值!
// 当前小图片 获取 data-target属性值
.attr("src",$(this).attr("data-target"))
//.prop() 不能改.prop()
})
</script>
</body>
</html>
运行结果:
-
样式:
(1). DOM中:
a. 如果只修改一个css属性: 元素.style.css属性=值
b. 获取一个元素的css属性: var style=getComputedStyle(元素)
c. 如果批量修改一个元素的多个css属性: 元素.className="class名"
(2). jq中:
a. 将修改css属性和获取css属性统一为一个: $元素.css("css属性名","属性值")
一个函数两用: 如果没传入新属性值,则自动执行读取旧属性值的操作,相当于getComputedStyle 如果传入新属性值,则自动切换为执行修改属性值的操作,相当于元素.style.css属性b. 如果批量修改一个元素的多个css属性,依然使用class的方式。
1). 问题: DOM中的className如果只想操作一个class名而不影响当前元素上其它class名,非常不方便!因为className是一个完整的字符串,只能整体替换所有class。 2). 解决: jq定义两个4个函数,专门对class执行不同的操作: i. $元素.addClass("class名") 添加class ii. $元素.removeClass("class名") 移除class iii. var bool=$元素.hasClass("class名") 判断是否包含某个class iv. $元素.toggleClass("class名") 切换有没有一个class ①等效于: if(有这个class hasClass()){ 就移除class removeClass() }else{ 就添加class addClass() } ②问题: 能不能用toggleClass完全代替前边的addClass和removeClass 答: 不能!addClass永远是添加class, removeClass永远是移除class,但是toggleClass没准: 一次添加,一次移除,再一次才是添加,再一次又是移除! ③总结: 只有确实在有和没有一个class之间来回切换时,才用toggleClass(3). 示例: 双态按钮
<!DOCTYPE html>
双态按钮
运行结果:```
简写: .attr()/.prop()/.css() 其实都可以一句话修改多个属性值
$元素.attr或prop或css({
属性名: 属性值,
... : ...
})
三. 按节点间关系查找:
-
父子关系:
(1). 获得一个元素的父元素: $元素.parent() 代替 元素.parentElement
(2). 获得一个元素下所有直接子元素: $元素.children() 代替 元素.children
a. 问题: children默认只能选择所有直接子元素,无法只选择个别想要的子元素
解决: $元素.children(选择器), 意为可以有选择的挑选部分符合条件的元素b. 问题: children默认只能在直接子元素中查找!无法在所有后代中查找
解决: $元素.find(选择器) 在所有后代元素中查找符合要求的元素(3). 获得一个元素下第一个直接子元素: 元素.firstElementChild
$元素.children(":first-child");(4). 获得一个元素下最后一个直接子元素: 元素.lastElementChild
$元素.children(":last-child"); -
兄弟关系:
(1). 前一个兄弟:
a. DOM中: 元素.previousElementSibling
b. jq中: $元素.prev()
c. 问题: 有时,不止找前一个元素,想找之前所有元素
解决: $元素.prevAll(选择器)(2). 下一个兄弟:
a. DOM中: 元素.nextElementSibling
b. jq中: $元素.next();
c. 问题: 有时,不止找下一个元素,想找之后所有元素
解决: $元素.nextAll(选择器)
解决: $元素.siblings("选择器")
- 示例: 使用按节点间关系查找,选择指定的元素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>...</title>
<script>
</script>
</head>
<body>
<!-- ul.top>(li.parent>ul>li.child*3)*2 -->
<ul class="top">
<li class="parent1">parent1
<ul>
<li class="child">child1</li>
<li class="child">child2</li>
<li class="child">child3</li>
</ul>
</li>
<li class="parent2">parent2
<ul>
<li class="child">child1</li>
<li class="child">child2</li>
<li class="child">child3</li>
</ul>
</li>
</ul>
<script src="js/jquery-1.11.3.js"></script>
<script>
//修改class为top的ul的所有直接子元素
$("ul.top").children().css("border","1px solid red")
//修改class为top的ul的所有后代li
$("ul.top").find("li").css("box-shadow","0 0 5px green")
//为class为child的li绑定单击事件
$("li.child").click(function(){
//选择当前元素的下一个元素/前一个元素/之前所有/之后所有/除自己之外所有
$(this).siblings()//.nextAll()//.prevAll()//.prev()//.next()
.css("background-color","yellow");
})
</script>
</body>
</html>
运行结果:
- 示例: 标签页效果
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.tabs {
list-style: none;
padding: 0
}
.tabs a {
text-decoration: none;
color: #000;
padding: 6px 12px;
display: inline-block;
}
.tabs>li {
float: left;
border-bottom: 1px solid #000;
}
.tabs>.active {
border: 1px solid #000;
border-bottom: 0;
}
</style>
</head>
<body>
<h1>使用属性选择器实现标签页头的切换</h1>
<ul class="tabs">
<li class="active"><a data-toggle="tab" href="#">十元套餐</a></li>
<li><a data-toggle="tab" href="#">二十元套餐</a></li>
<li><a data-toggle="tab" href="#">三十元套餐</a></li>
</ul>
<script src="js/jquery-1.11.3.js"></script>
<script>
//DOM 4步
//1 查找触发事件的元素
//本例中: 用户点有data-toggle属性,且属性值为tab的元素触发变化
$("[data-toggle=tab]")
//2. 绑定事件处理函数
//本例中: 单击触发变化
.click(function(){
//3. 查找要修改的元素
//4. 修改元素
//本例中: 先给当前a的父元素li加active class,再去掉当前a的父元素里的兄弟身上的active class
$(this).parent()
// a 当前li
.addClass("active")//本来不需要返回值
//jQuery要求addClass必须返回.前的主语
//return $当前li
//addClass的返回值,刚巧和下一个操作的.前的主语一致!
.siblings().removeClass("active");
// 其它li
//jquery链式操作!
})
</script>
</body>
</html>
运行结果:
四. 添加/删除/替换/克隆:
-
添加: (1). 回顾: DOM中: 3步:
a. 创建新元素: var 新元素=document.createElement("标签名")
b. 设置关键属性: 元素.属性名=属性值
c. 将新元素添加到DOM树: 3种:
1). 父元素末尾追加新元素: 父元素.appendChild(新元素) 2). 插入到父元素下一个现有子元素之前: 父元素.insertBefore(新元素, 现有子元素) 3). 替换父元素下一个现有子元素: 父元素.replaceChild(新元素, 现有子元素)(2). jq中: 2步:
a. 用一段HTML片段创建一个或多个元素:
var $新元素=$(`HTML代码片段`);问题: 依然是在内存中游离的,没有在DOM树上!所以,页面上暂时看不到
解决: 挂载
b. 将新元素添加到DOM树: 5种情况,10个函数
1). 父元素末尾追加新元素: $父元素.append($新元素) 代替 父元素.appendChild(新元素) 兄弟函数: $新元素.appendTo($父元素) 2). 父元素开头插入新元素: 新增: $父元素.prepend($新元素) 兄弟函数: $新元素.prependTo($父元素) 3). 插入到一个现有子元素之前: $现有元素.before($新元素) 代替 父元素.insertBefore(新元素, 现有子元素) 兄弟函数: $新元素.insertBefore($现有元素) 4). 插入到一个现有子元素之后: 新增: $现有元素.after($新元素) 兄弟函数: $新元素.insertAfter($现有元素) 5). 替换父元素下一个现有子元素: $现有元素.replaceWith($新元素) 父元素.replaceChild(新元素, 现有子元素) 兄弟函数: $新元素.replaceAll($现有元素)
为什么每个函数又多出一个功能一模一样,只是主语和宾语颠倒位置的新函数?
因为主语不同,则函数返回的jquery对象不用。则后续可连接的链式操作也就不同!
如果希望在追加一个新元素后,继续对新元素执行下一步操作:
不好的做法: $父元素.append($新元素)
return $父元素,下一步用不了!
$新元素.下一步操作
好的做法: $新元素.appendTo($父元素).下一步操作()
return $新元素 下一步可继续使用
-
删除: $元素.remove()
-
示例: 点按钮,添加方块,点x删除方块
<!DOCTYPE html>
<html>
<head>
<title> new document </title>
<meta charset="utf-8">
<style>
.container {
border: 1px solid #aaa;
overflow: hidden;
}
.block {
float: left;
margin: 10px;
border: 1px solid #aaa;
background: #faa;
width: 150px;
height: 150px;
}
.block:hover {
box-shadow: 0 5px 6px #000;
}
.close {
float: right;
padding: 5px;
font-weight: bold;
opacity: .2;
cursor: pointer;
}
.close:hover {
opacity: .5;
}
</style>
</head>
<body>
<h1>添加/删除节点</h1>
<button id="add-block">添加区块</button>
<div class="container">
<!-- <div class="block">
<span class="close">×</span>
</div> -->
</div>
<script src="js/jquery-1.11.3.js"></script>
<script>
//DOM 4步
//1. 查找触发事件的元素
//本例中: 点击按钮添加方块
$("#add-block")
//2. 绑定事件处理函数
.click(function(){
// //3. 查找要修改的元素
// //本例中: 向class="container"的div开头插入一个新方块div元素
// var $container=$(".container");
// //4. 修改元素
// //本例中:
// //先创建一个新的方块元素对象
// var $block=$(`<div class="block">
// <span class="close">×</span>
// </div>`);
// //设置方块的随机背景色
// $block.css("background-color",`rgb(${
// parseInt(Math.random()*256)
// },${
// parseInt(Math.random()*256)
// },${
// parseInt(Math.random()*256)
// })`);
// //最后将方块插入到$container开头
// $container.prepend($block);
//创建一个新方块
$(`<div class="block">
<span class="close">×</span>
</div>`)
//设置方块的随机背景色
.css("background-color",`rgb(${
parseInt(Math.random()*256)
},${
parseInt(Math.random()*256)
},${
parseInt(Math.random()*256)
})`)
//return 新方块
//将方块插入到父元素开头
//.prependTo($(".container"))
//简写: 不用自己找.container,直接把选择器给prependTo,prependTo会自动查找选择器所指的父元素
.prependTo(".container");
})
//实现点x按钮删除当前方块
//DOM 4步
//1. 查找触发事件的元素
//本例中: 因为多个x都可单击,所以应该用事件委托优化——复习事件委托
//事件应该只绑定在父元素上一份即可
$(".container")
//2. 绑定事件处理函数
//本例中: 应该先获得事件对象e,才能用e.target获得目标元素x
.click(function(e){
//获得当前点击的元素
var $target=$(e.target);
//判断当前实际点的元素是否是想要的
//本例中: 只有点在class为close的span元素上,才能删除
if($target.hasClass("close")){ //说明我们点的是x
//3. 查找要修改的元素
//本例中: 点x,其实是要删除x的父元素div
$target.parent()
//4. 修改元素
//本例中: 删除父元素div
.remove();
}
})
</script>
</body>
</html>
运行结果: