Web前端基础(15)jQuery选择器和DOM操作

jQuery是JavaScript中使用最广泛的一个库,它可以帮助我们简化js代码,更好的完成工作。

痛点

javascript遇到的一些痛点:

  • window.onload 事件有个覆盖问题,我们只能写一个
  • 代码容错性差
  • 浏览器兼容性问题
  • 书写很繁琐,代码量多
  • 代码很乱,各个页面到处都是
  • 动画效果,我们很难实现

版本

目前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,只支持最新的浏览器。除非特殊要求,一般不会使用3.x版本的,很多老的jQuery插件不支持这个版本。目前该版本是官方主要更新维护的版本。最新版本:3.3.1

引入

使用jQuery只需要在页面的

引入jQuery文件即可

1
2
3
4
5
6
7
8
9
<html>
<head>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
...
</head>
<body>
...
</body>
</html>

$符号

$是著名的jQuery符号。实际上,jQuery把所有功能全部封装在一个全局变量jQuery中,而$也是一个合法的变量名,它是变量jQuery的别名:

1
2
3
4
window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'

jQuery入口函数

1
2
3
4
//方法1:
$(document).ready(function(){});
//方法2:
$(function(){});

javascript的入口函数和jquery的入口函数区别:

  1. javascript的window.onload事件是等到所有内容,以及我们外部图片之类的文件加载完了之后,才会去执行。jQuery入口函数是在html所有标签都加载进去后执行。
  2. jQuery入口函数不会有被覆盖问题。

选择器

jQuery的基本选择器

符号说明
$(“#demo”)选择id为dem的第一个元素
$(“.item”)选择所有class=”item”的元素
$(“div”)选择所有div标签
$(“*”)选择所有元素(建议配合其他选择器使用)
$(“.item, div”)组合选择器(选择class=”item”和div选择器)
$(“div span)交集选择器(选择div标签下的所有span标签)
$(“div > span”)子元素选择器(选择div的子标签中的span标签(只是直接子标签))
$(“div + span”)相邻元素选择器(选择div相邻的span)

层级选择器

如果两个DOM元素具有层级关系,就可以用$(‘ancestor descendant’)来选择,层级之间用空格隔开。例如:

1
2
3
4
5
6
7
8
<!-- HTML结构 -->
<div class="testing">
<ul class="lang">
<li class="lang-javascript">JavaScript</li>
<li class="lang-python">Python</li>
<li class="lang-lua">Lua</li>
</ul>
</div>

子选择器

子选择器$(‘parent>child’)类似层级选择器,但是限定了层级关系必须是父子关系,就是节点必须是节点的直属子节点。还是以上面的例子:

1
2
$('ul.lang>li.lang-javascript'); // 可以选出[<li class="lang-javascript">JavaScript</li>]
$('div.testing>li.lang-javascript'); // [], 无法选出,因为<div>和<li>不构成父子关系

过滤器

过滤器一般不单独使用,它通常附加在选择器上,帮助我们更精确地定位元素。观察过滤器的效果:

1
2
3
4
5
6
7
$('ul.lang li'); // 选出JavaScript、Python和Lua 3个节点

$('ul.lang li:first-child'); // 仅选出JavaScript
$('ul.lang li:last-child'); // 仅选出Lua
$('ul.lang li:nth-child(2)'); // 选出第N个元素,N从1开始
$('ul.lang li:nth-child(even)'); // 选出序号为偶数的元素
$('ul.lang li:nth-child(odd)'); // 选出序号为奇数的元素

jQuery中的基本过滤选择器

符号说明
:eq(index)index是从0开始,表示第index+1个匹配的元素
:gt(index)选择序号大于index的元素
:lt(index)选择序号小于index的元素
:odd序号为奇数的
:even序号为偶数的
:first选择第一个匹配的元素
:last选择最后一个匹配的元素

属性选择器

jQuery中常用的属性选择器

符号说明
$(“a[href]”)选择所有包含href属性的元素
$(“a[href=’label’]”)选择属性为href=”label”的元素
$(“a[href!=’label’]”)选择属性不是href=”label”的元素
$(“a[href^=’label’]”)选择所有href以label开头的元素
$(“a[href$=’label’]”)选择所有href以label结尾的元素
$(“a[href*=’label’]”)选择所有href中包含label的元素
$(“a[href][title=’我’]”)选择所有包含href属性并且title=”我”的元素

查找

通常情况下选择器可以直接定位到我们想要的元素,但是,当我们拿到一个jQuery对象后,还可以以这个对象为基准,进行查找和过滤。

最常见的查找是在某个节点的所有子节点中查找,使用find()方法,它本身又接收一个任意的选择器。例如如下的HTML结构:

1
2
3
4
5
6
7
8
<!-- HTML结构 -->
<ul class="lang">
<li class="js dy">JavaScript</li>
<li class="dy">Python</li>
<li id="swift">Swift</li>
<li class="dy">Scheme</li>
<li name="haskell">Haskell</li>
</ul>

用find()查找子节点

1
2
3
4
var ul = $('ul.lang'); // 获得<ul>
var dy = ul.find('.dy'); // 获得JavaScript, Python, Scheme
var swf = ul.find('#swift'); // 获得Swift
var hsk = ul.find('[name=haskell]'); // 获得Haskell

用parent()查找父节点

1
2
3
var swf = $('#swift'); // 获得Swift
var parent = swf.parent(); // 获得Swift的上层节点<ul>
var a = swf.parent('.red'); // 获得Swift的上层节点<ul>,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象

用next()和prev()查找同层级

1
2
3
4
5
6
7
var swift = $('#swift');

swift.next(); // Scheme
swift.next('[name=haskell]'); // 空的jQuery对象,因为Swift的下一个元素Scheme不符合条件[name=haskell]

swift.prev(); // Python
swift.prev('.dy'); // Python,因为Python同时符合过滤器条件.dy

过滤

和函数式编程的map、filter类似,jQuery对象也有类似的方法。

filter()方法可以过滤掉不符合选择器条件的节点:

1
2
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var a = langs.filter('.dy'); // 拿到JavaScript, Python, Scheme

或者传入一个函数,要特别注意函数内部的this被绑定为DOM对象,不是jQuery对象:

1
2
3
4
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
langs.filter(function () {
return this.innerHTML.indexOf('S') === 0; // 返回S开头的节点
}); // 拿到Swift, Scheme

map()方法把一个jQuery对象包含的若干DOM节点转化为其他对象:

1
2
3
4
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var arr = langs.map(function () {
return this.innerHTML;
}).get(); // 用get()拿到包含string的Array:['JavaScript', 'Python', 'Swift', 'Scheme', 'Haskell']

此外,一个jQuery对象如果包含了不止一个DOM节点,first()、last()和slice()方法可以返回一个新的jQuery对象,把不需要的DOM节点去掉:

1
2
3
4
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var js = langs.first(); // JavaScript,相当于$('ul.lang li:first-child')
var haskell = langs.last(); // Haskell, 相当于$('ul.lang li:last-child')
var sub = langs.slice(2, 4); // Swift, Scheme, 参数和数组的slice()方法一致

DOM操作

直接使用浏览器提供的API对DOM结构进行修改,不但代码复杂,而且要针对浏览器写不同的代码。

有了jQuery,我们就专注于操作jQuery对象本身,底层的DOM操作由jQuery完成就可以了,这样一来,修改DOM也大大简化了。

添加DOM

要添加新的DOM节点,除了通过jQuery的html()这种暴力方法外,还可以用append()方法,例如:

1
2
3
4
5
6
7
<div id="test-div">
<ul>
<li><span>JavaScript</span></li>
<li><span>Python</span></li>
<li><span>Swift</span></li>
</ul>
</div>

如何向列表新增一个语言?首先要拿到

    节点:

1
var ul = $('#test-div>ul');

然后,调用append()传入HTML片段:

1
ul.append('<li><span>Haskell</span></li>');

除了接受字符串,append()还可以传入原始的DOM对象,jQuery对象和函数对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建DOM对象:
var ps = document.createElement('li');
ps.innerHTML = '<span>Pascal</span>';
// 添加DOM对象:
ul.append(ps);

// 添加jQuery对象:
ul.append($('#scheme'));

// 添加函数对象:
ul.append(function (index, html) {
return '<li><span>Language - ' + index + '</span></li>';
});

append()把DOM添加到最后,prepend()则把DOM添加到最前。

另外注意,如果要添加的DOM节点已经存在于HTML文档中,它会首先从文档移除,然后再添加,也就是说,用append(),你可以移动一个DOM节点。

同层级之间可以用用after()或者before()方法。

删除节点

remove方法

要删除DOM节点,拿到jQuery对象后直接调用remove()方法就可以了。如果jQuery对象包含若干DOM节点,实际上可以一次删除多个DOM节点:

1
2
var li = $('#test-div>ul>li');
li.remove(); // 所有<li>全被删除

detach方法

detach()和remove()一样,是从DOM中去掉所有匹配元素,但是不会把jQuery对象中删除,所有关于该节点的事件、附加的数据都会保留下来。

empty方法

empty方法不是删除节点,而是清空元素中的所有后代节点。

复制节点

可用通过clone()方法来复制节点,clone()方法可以传一个boolean参数,如果传true表示复制元素的同时也复制元素中所绑定的事件。

1
$(this).clone(true).appendTo("body");

替换节点

jQuery提供了replaceWith()和replaceAll()方法来替换节点

replaceWith()方法作用是将所有匹配的元素都替换成制定的html或者DOM元素。

1
$("p").replaceWith("<strong>我会把你这个节点替换掉</strong>")

replaceAll()和replaceWith()的作用相同,知识颠倒了操作。

1
$("<strong>我会把里面的所有你都替换掉</strong>").replaceAll("p");

包裹节点

1
$("strong").wrap("<b></b>") //用b标签把<strong>元素包裹起来

包裹元素还有wrapAll()和wrapInner()方法, 与wrap()的区别如下:

1
2
3
4
5
6
<strong>有线网络</strong>
<strong>无线网络</strong>
<ul>
<li>GY</li>
<li>NetChina</li>
</ul>

如果使用wrap()

1
2
3
4
5
$("strong").wrap("<b></b>");

//结果
//<b><strong>有线网络</strong></b>
//<b><strong>无线网络</strong></b>

如果使用wrapAll()方法

1
2
3
4
5
6
7
$("strong").wrapAll("<b></b>");

//结果
//<b>
// <strong>有线网络</strong>
// <strong>无线网络</strong>
//</b>

如果用wrapInner()方法

1
2
3
4
5
$("strong").wrapInner("<b></b>");

//结果
//<strong><b>有线网络</b></strong>
//<strong><b>无线网络</b></strong>

插入节点

方法描述
append()匹配元素内部追加(父子节点)
appendTo()和append()颠倒A.appendTo(B) == B.append(A)
prepend()匹配元素内部最前面插入
prependTo()A.prependTo(B) == B.prepend(A)
after()在匹配元素之后插入(兄弟节点)
insertAfter()A.inertAfter(B) == B.after(A)
before()在匹配元素之前插入(兄弟节点)
insertBefore()A.intertBefore(B) == B.before(A)

DOM对象和jQuery对象切换

在jQuery对象中无法使用DOM对象的任何方法,可以用jQuery类似的方法代替,DOM对象也不能使用jQuery的方法。

$(dom对象) ==> jQuery对象

$(“#btn”)[0] 或者 $(“#btn”).get(0) ==> DOM对象

下拉菜单Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div class="wrap">
<ul>
<li><a href="#">一级菜单1</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
<li><a href="#">一级菜单2</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
<li><a href="#">一级菜单3</a>
<ul>
<li><a href="">二级菜单1</a></li>
<li><a href="">二级菜单2</a></li>
<li><a href="">二级菜单3</a></li>
</ul>
</li>
</ul>
</div>

css 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
*{padding: 0; margin: 0;}

ul{
list-style: none;
}

.wrap{
width: 331px;
height: 30px;
margin: 100px auto 0;
background: #888;
padding-left: 10px;
border-radius: 4px;
}

.wrap li{
float: left;
width: 100px;
height: 30px;
margin-right: 10px;
position: relative;
}

.wrap a{
color: black;
text-decoration:none;
display:block;
width: 100px;
height: 28px;
text-align: center;
line-height: 28px;
background: #FFCF00;
border-radius: 6px;
border:1px solid #FF8626;
color: #666;
}

.wrap li ul{
position: absolute;
display: none;
}

js实现

1
2
3
4
5
6
7
8
9
$(document).ready(function(){
$(".wrap li").mouseenter(function(){
$(this).children("ul").show();
});

$(".wrap li").mouseleave(function(){
$(this).children("ul").hide();
});
});

mouseover/mouseout和mouseenter/mouseleave区别

mouseover其中的所有元素进入都会事件触发一次, mouseenter只会触发一次,所以上面使用的是mouseenter.

三种变体写法

第一种:

1
2
3
4
5
$(".wrap li").hover(function(){
$(this).children("ul").show();
}, function(){
$(this).children("ul").hide();
})

第二种:

1
2
3
4
5
6
7
8
9
$(".wrap li").hover(function(){
var $this = $(this).children("ul");
var isShow = $this.css("display");
if(isShow === "block"){
$this.hide();
}else{
$this.show();
}
});

第三种:

1
2
3
$(".wrap li").hover(new function(){
$(this).children("ul").slideToggle();
});

slideToggle()方法是在显示和隐藏之间切换的动画。

本文部分内容参考自廖雪峰的官方网站

评论

Ajax Android AndroidStudio Animation Anroid Studio AppBarLayout Banner Buffer Bulma ByteBuffer C++ C11 C89 C99 CDN CMYK COM1 COM2 CSS Camera Raw, 直方图 Chrome ContentProvider CoordinatorLayout C语言 DML DOM Dagger Dagger2 Darktable Demo Document DownloadManage Element Error Exception Extensions File FileProvider Fresco GCC Git GitHub GitLab Gradle Groovy HTML5 Handler HandlerThread Hexo Hybrid I/O IDEA IO ImageMagick IntelliJ Intellij Interpolator JCenter JNI JS Java JavaScript JsBridge Kotlin Lab Lambda Lifecycle Lint Linux Looper MQTT MVC MVP Maven MessageQueue Modbus Momentum MySQL NDK NIO NexT Next Nodejs ObjectAnimator Oracle VM Permission PhotoShop Physics Python RGB RS-232 RTU Remote-SSH Retrofit Runnable RxAndroid RxJava SE0 SSH Spring SpringBoot Statubar Task Theme Thread Tkinter UI UIKit UML VM virtualBox VS Code ValueAnimator ViewPropertyAnimator Web Web前端 Workbench api apk bookmark by关键字 compileOnly css c语言 databases demo hexo hotfix html iOS icarus implementation init jQuery javascript launchModel logo merge mvp offset photos pug query rxjava2 scss servlet shell svg tkinter tomcat transition unicode utf-8 vector virtual box vscode 七牛 下载 中介者模式 串口 临潼石榴 主题 书签 事件 享元模式 仓库 代理模式 位运算 依赖注入 修改,tables 光和色 内存 内核 内部分享 函数 函数式编程 分支 分析 创建 删除 动画 单例模式 压缩图片 发布 可空性 合并 同向性 后期 启动模式 命令 命令模式 响应式 响应式编程 图层 图床 图片压缩 图片处理 图片轮播 地球 域名 基础 增加 备忘录模式 外观模式 多线程 大爆炸 天气APP 太白山 头文件 奇点 字符串 字符集 存储引擎 宇宙 宏定义 实践 属性 属性动画 岐山擀面皮 岐山肉臊子 岐山香醋 工具 工厂模式 年终总结 开发技巧 异常 弱引用 恒星 打包 技巧 指针 插件 摄影 操作系统 攻略 故事 数据库 数据类型 数组 文件 新功能 旅行 旋转木马 时序图 时空 时间简史 曲线 杂谈 权限 枚举 架构 查询 标准库 标签选择器 样式 核心 框架 案例 桥接模式 检测工具 模块化 模板引擎 模板方法模式 油泼辣子 泛型 洛川苹果 浅色状态栏 源码 瀑布流 热修复 版本 版本控制 状态栏 状态模式 生活 留言板 相册 相对论 眉县猕猴桃 知识点 码云 磁盘 科学 笔记 策略模式 类图 系统,发行版, GNU 索引 组件 组合模式 结构 结构体 编码 网易云信 网格布局 网站广播 网站通知 网络 美化 联合 膨胀的宇宙 自定义 自定义View 自定义插件 蒙版 虚拟 虚拟机 补码 补齐 表单 表达式 装饰模式 西安 观察者模式 规范 视图 视频 解耦器模式 设计 设计原则 设计模式 访问者模式 语法 责任链模式 贪吃蛇 转换 软件工程 软引用 运算符 迭代子模式 适配器模式 选择器 通信 通道 配置 链表 锐化 错误 键盘 闭包 降噪 陕西地方特产 面向对象 项目优化 项目构建 黑洞
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×