古之立大事者,不惟有超世之才,亦必有坚忍不拔之志——苏轼
先说概念
选择器是什么
jQuery 的选择器是用于定位 HTML 页面中的元素,其用法最初设计时源于 CSS 的选择器用法,但是 jQuery 的选择器进行了扩展,远比 CSS 的选择器更强大。
其实在 JavaScript 中的 DOM 也具有类似的用法。例如 querySelector()
方法和 querySelectorAll()
方法,就是利用 CSS 选择器定位页面元素。但 jQuery 中的选择器性能要比 DOM 中的更好。
jQuery 的选择器是将工厂函数作为容器,具体语法如下:
var element = $(selector)
// 或者
var element = jQuery(selector)
- 参数
selector
: 表示 jQuery 的选择器 - 返回值
element
: jQuery 的工厂函数会返回一个 jQuery 对象。
jQuery 选择器的分类
jQuery 选择器的种类众多,我们可以将其分为以下几类:
- 基本选择器
- 层级选择器
- 基本过滤选择器
- 内容过滤选择器
- 可见性选择器
- 属性过滤选择器
- 子元素过滤选择器
- 表单对象属性过滤选择器
- 表单选择器
jQuery 中的选择器众多,我们并不需要全部记住,只需要记住这些选择器的用法,具体内容可以查看帮助文档
基本选择器
jQuery 中的基本选择器具有以下几种,如下表所示
选择器 | 描述 |
---|---|
ID 选择器 | 根据给定的 ID 匹配一个元素 |
元素选择器 | 根据给定的元素名称匹配元素 |
类选择器 | 根据给定的 CSS 类名匹配元素 |
通配符选择器 | 匹配所有的元素 |
组合选择器 | 将每一个选择器匹配到的元素合并后一起返回 |
值得注意的是,由于 jQuery 对象是类数组对象,及时匹配的元素只有一个,返回的结果依旧是类数组对象.
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基本选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div id="div1" class="cls1">前端无限好</div>
<div id="div2" class="cls2">我爱大前端</div>
<script>
// ID 选择器 -> 根据给定的 id 属性匹配元素
console.log($('#div1')); // jQuery.fn.init(1) 获取到一个
// 元素选择器
console.log($('div')); // jQuery.fn.init(2) 获取到两个
// 类选择器
console.log($('.cls1')); // jQuery.fn.init(1) 获取到一个
// 通配符选择器
console.log($('*')); // jQuery.fn.init(10) 获取当前页面全部元素
// 组合选择器 -> 并集选择器,并集选择器 通过 , 逗号分隔
console.log($('.cls1, .cls2')); // jQuery.fn.init(2) 获取到两个
// 组合选择器 -> 交集选择器, 交集选择器之前没有任何分隔。
console.log($('#div1.cls1')); // jQuery.fn.init(1) 获取到一个
</script>
</body>
</html>
泽合选择器的选择过程如下图所示
层级选择器
jQuery 的层级选择器具有以下几种:
选择器 | 描述 |
---|---|
后代选择器 | 根据给定的祖先元素下匹配所有的后代元素 |
子选择器 | 根据给定的父元素下匹配所有的子元素 |
相邻兄弟选择器 | 根据给定的目标元素匹配下一个相邻兄弟元素 |
普通兄弟选择器 | 根据给定的目标元素匹配后面所有兄弟元素 |
值得注意的是,相邻兄弟选择器和普通兄弟选择器仅仅会获取目标元素的后面元素,不会获取前面的元素
先看一段 HTML 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML测试代码</title>
</head>
<body>
<div>
<p></p>
<p></p>
</div>
<div>
<span></span>
<button></button>
<span></span>
</div>
</body>
</html>
将如上代码可以画成如下节点树,如下图所示
在此 HTML 结构中,表中除 <html>
元素外,其余元素都是 HTML 的后代元素,当然,<p>
也是 body
的后代元素,这就是祖先与后代的关系。
第一个<div>
元素是 <p>
元素的父元素,反过来说就是 <p>
元素是 第一个 <div>
元素的子元素,这就是父与子的关系。
<span>
元素 和 <span>
元素是普通兄弟元素,因为中间夹着一个 <button>
元素。
<button>
元素和 <span>
元素是相邻兄弟元素,<span>
元素和 <button>
元素是也相邻兄弟元素
jQuery 选择器的实例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>层次选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div id="container">
<div class="parent">
<div class="child0">1</div>
<div id="child" class="child0">1</div>
<div class="child0">1</div>
<div class="child0">1</div>
</div>
<div class="parent">
<div class="child">1</div>
<div class="child1">2</div>
<div class="child">3</div>
</div>
</div>
<script>
// 后代选择器,符号 空格
console.log($('#container div'));
// 子选择器,符号是大于号 >
console.log($('#container>div'));
// 相邻兄弟选择器,获取下一个兄弟元素 符号是 +
console.log($('.child1+div'));
// 普通兄弟选择器 获取后面的元素,符号是 ~
console.log($('#child~.child0'));
</script>
</body>
</html>
执行结果所示
jQuery 还提供了 siblings([expr])
方法,通过其他方式获取一个包含匹配的元素集合中每一个元素的所有唯一同辈元素的元素集合。可以用可选的表达式进行筛选。
示例代码如下所示
console.log($('#child').siblings());
// jQuery.fn.init(3) [div.child0, div.child0, div.child0, prevObject: jQuery.fn.init(1), context: document]
siblings([expr])
方法属于过滤选择器
基本过滤选择器
所谓的过滤选择器就是通过某种筛选规则将一些不满足的元素给过滤掉,jQuery 中提供的基本过滤选择器具有如下几种:
选择器 | 描述 |
---|---|
:first 过滤选择器 | 获取第一个元素 |
:last 过滤选择器 | 获取最后一个元素 |
:even 过滤选择器 | 匹配所有索引值为偶数的元素,从 0 开始计数 |
:odd 过滤选择器 | 匹配所有索引值为奇数的元素,从 0 开始计数 |
:eq(index) 过滤选择器 | 匹配一个给定索引值的元素 |
:gt(index) 过滤选择器 | 匹配所有大于给定索引值的元素 |
:lt(index) 过滤选择器 | 匹配素有小于给定索引值的元素 |
:not(element) 过滤选择器 | 去除所有与给定选择器匹配的元素 |
:header 过滤选择器 | 匹配 <h1>~<h6> 标题元素 |
:animated 过滤选择器 | 匹配所有正在执行动画效果的元素 |
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基本过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<h1>狐妖小红娘</h1>
<div class="preson frist">涂山红红</div>
<div class="preson">涂山苏苏</div>
<div class="preson other">涂山雅雅</div>
<div class="preson other">涂山容容</div>
<div class="preson">东方月初</div>
<div class="preson">白月初</div>
<div class="preson other">王权富贵</div>
<div class="preson other last">王富贵</div>
<script>
// 匹配第一个元素
console.log($('.preson:first'));
// 匹配最后一个元素
console.log($('.preson:last'));
// 匹配索引值为奇数的元素
console.log($('.preson:even'));
// 匹配索引值为偶数的元素
console.log($('.preson:odd'));
// 匹配索引值为4的元素
console.log($('.preson:eq(4)'));
// 匹配索引值大于3的元素
console.log($('.preson:gt(3)'));
// 匹配索引值小于5的元素
console.log($('.preson:lt(5)'));
// 匹配结果中不包含 ".other" 的元素,值得注意的是,如果使用的是单引号,那 :not("") 括号中必须使用单引号
console.log($('.preson:not(".other")'));
// 匹配 h1~h6
console.log($(':header'));
// 匹配带有动画的元素,一般情况下仅匹配 jQuery 实现的动画
console.log($(':animated'));
</script>
</body>
</html>
执行结果如下图所示:
内容过滤选择器
jQuery 中提供的内容过滤选择器就是通过过滤文本内容来选择元素的,jQuery 中提供的内容过滤选择器如下表所示:
选择器 | 描述 |
---|---|
:contains(text) | 匹配包含给定文本的元素 |
:empty | 匹配所有不包含子元素或者文本的空元素 |
:has(selector) | 匹配含有选择器所匹配的元素的元素 |
:parent | 匹配含有子元素或者文本的元素 |
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>内容过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div class="person">涂山苏苏</div>
<div class="parent">
<div class="child"></div>
</div>
<script>
// 通过 :contains() 获取指定内容为涂山苏苏的元素
var $susu = $('div:contains("涂山苏苏")');
// 将 $susu 转换为 DOM 对象
console.log($susu[0]);
// 通过 :empty 获取属性名为div的空元素
var $empty = $('div:empty')
// 转换为 DOM 对象
console.log($empty[0]);
// 通过 :has(selector) 获取包含 .child 的名为 div 元素
var $hasChild = $('div:has(.child)')
// 转换为 DOM 对象
console.log($hasChild[0]);
// 通过 :parent 获取含有子元素或者文本的所有 div 元素 从代码中看其包含两个
var $parent = $('div:parent')
// 转换为 DOM 对象
console.log($parent[0]);
console.log($parent[1]);
</script>
</body>
</html>
执行结果如下图所示:
可见性过滤选择器
jQuery 中提供的可见性过滤选择器可以根据元素的是否可见来筛选元素,jQuery 中提供的可见性过滤选择器如下表所示:
选择器 | 描述 |
---|---|
:hidden | 匹配所有不可见元素,或者 type 为 hidden 的元素 |
:visible | 匹配所有的可见元素 |
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>可见性过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div style="display: none;">块级元素</div>
<button style="visibility: hidden;">按钮</button>
<h1>一级标题</h1>
<input type="hidden" name="input元素">
<script>
/*
:hidden 选择器
* 匹配不到 CSS 样式属性 visibility 设置为 hidden 的隐藏元素,但是可以匹配 type 为 hidden 的隐藏元素
* 除此之外还可以匹配 HMLT 页面中不做任何显示效果的元素
* 用此选择器的时候尽量确定元素的类型或者范围
*/
console.log($(':hidden'));
/*
:visible 选择器
* 可以匹配 CSS 样式属性 visibility 设置为 hidden 的隐藏元素
* 还能匹配 html 和 body 元素
*/
console.log($(':visible'));
</script>
</body>
</html>
执行结果如下图所示:
属性过滤选择器
jQuery 的属性过滤选择器具有以下几种
[attr]
属性过滤选择器:通过 HTML 元素的 attr 属性名来匹配具体 HTML 元素,而不关注 attr 属性的值是什么。[attr=value]
属性过滤选择器:通过 HTML 元素的 attr 属性名并且属性值为 value 来匹配具体 HTML 元素。[attr!=value]
属性过滤选择器:通过 HTML 元素的 attr 属性名并且属性值为 value 来匹配具体 HTML 元素。[attr^=value]
属性过滤选择器:通过 HTML 元素的 attr 属性名并且属性值是以 value 为开头来匹配具体 HTML 元素。[attr$=value]
属性过滤选择器:通过 HTML 元素的 attr 属性名并且属性值是以 value 为结束来匹配具体 HTML 元素。[attr*=value]
属性过滤选择器:通过 HTML 元素的 attr 属性名并且属性值是包含 value 来匹配具体 HTML 元素。
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>属性过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div class="mydiv" name="div1" id="username"></div>
<div class="mycls" name="div2" id="passwd"></div>
<div class="mydiv" name="div3" id="use"></div>
<div class="mycls" name="div4"></div>
<script>
// [attr] 属性过滤选择器
console.log($('div[name]'));
// [attr = value] 属性过滤选择器
console.log($('div[name=div1]'));
// [attr != value] 属性过滤选择器
// 包含没有id属性的元素
console.log($('div[id!=use]'));
// [attr ^= value] 属性过滤选择器
console.log($('div[id^=us]'));
// [attr $= value] 属性过滤选择器
console.log($('div[class$=v]'));
// [attr *= value] 属性过滤选择器
console.log($('div[id*=a]'));
</script>
</body>
</html>
执行结果如下图所示
子元素过滤选择器
jQuery 的子元素过滤选择器具有以下几种:
选择器 | 描述 |
---|---|
:nth-child | 匹配其父元素下的第N个子或奇偶元素 |
:first-child | 匹配所给选择器( :之前的选择器 )的第一个子元素 |
:last-child | 匹配最后一个子元素 |
:only-child | 如果某个元素是父元素中唯一的子元素,那将会被匹配 |
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子元素过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<div id="parent">
<div class="child"></div>
<div class="child">
<id id="child"></id>
</div>
<div class="child"></div>
</div>
<script>
// :nth-child(index) 匹配当前元素的第index个子元素
// index从1开始
console.log($('div:nth-child(1)'));
// :first-child -当前元素是否为第一个子元素 包含body
console.log($('div:first-child'));
// :last-child 匹配最后一个子元素 不包含 body
console.log($('div:last-child'));
// :only-child 匹配唯一一个子元素 不包含 body
console.log($('div:only-child'));
</script>
</body>
</html>
执行结果如下图所示
表单对象属性过滤选择器
jQuery 的表单对象属性过滤选择器具有以下几种:
选择器 | 描述 |
---|---|
:enabled | 匹配所有可用元素 |
:disabled | 匹配所有不可用元素 |
:checked | 匹配所有选中的被选中元素(复选框、单选框等,select 中的 option) |
:selected | 匹配所有选中的 option 元素 |
示例代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单对象属性过滤选择器</title>
<script src="./library/jQuery 1.12.4.js"></script>
</head>
<body>
<form action="#">
<!-- disabled 表示 不可用 -->
<input type="text" disabled>
<!-- 被选中 -->
<input type="checkbox" checked>
<select>
<option>涂山</option>
<option selected>北山</option>
<option>傲来国</option>
</select>
</form>
<script>
// 匹配表单可用属性
console.log($('input:enabled'));
// 匹配表单不可用属性
console.log($('input:disabled'));
// 匹配所有选中的被选中元素
console.log($('input:checked'));
// 匹配所有选中的 option 元素
console.log($('option:selected'));
</script>
</body>
</html>
表单选择器
jQuery 的表单选择器具有很多,具体如下所示:
选择器 | 描述 |
---|---|
:input | 匹配所有 <input> 、 <textarea> 、 <select> 和 <button> 元素 |
:text | 匹配所有单行文本框 |
:password | 匹配所有密码框 |
:radio | 匹配所有单行选框 |
:checkbox | 匹配所有复选框 |
:submit | 匹配所有提交按钮 |
:image | 匹配所有图像域 |
:reset | 匹配所有重置按钮 |
:button | 匹配所有按钮 |
:file | 匹配所有文件域 |
表单选择器比较多,用法也比较单一,这里不做测试了就。
模拟jQuery的工厂函数
我们可以手动实现 jQuery 工厂函数的确定页面元素功能,这边仅仅实现其基本选择器的功能。
基本思路如下
- 定义一个函数 接受一个字符串参数
- 定义一个存储 元素的数组
- 截取字符串中的第一个字符,根据此字符来判断是那个选择器
- 根据截取的字符串内容,来判断属于哪一个选择器,并调用 DOM 中相应的方法
- 将数组返回
- 定义一个自调函数,并将此函数放入自调函数,并开放给全局作用域
示例代码如下
(function (global) {
// 定义一个工厂函数 - 接受字符串类型的选择器
var woQuery = function (selector) {
// 判断参数 select 必须是字符串类型
if (typeof selector === 'string') {
// 定义一个存储 元素的数组
var elementArr = []
// 截取第一个字符,根据此字符来判断是那个选择器
var strIndex = selector.substring(0, 1);
if (strIndex === '#') {
// 实现ID 选择器的功能
var strId = selector.substring(1, selector.length);
// 返回一个 DOM 对象
// return document.getElementById(strId)
// 将结果追加到数组中
elementArr.push(document.getElementById(strId))
} else if (strIndex === '.') {
// 实现ID 选择器的功能
var strClass = selector.substring(1, selector.length);
// 返回一个 DOM 对象
// return document.getElementsByClassName(strClass)
// 将结果追加到数组中
var classNames = document.getElementsByClassName(strClass)
for (i in classNames) {
elementArr.push(classNames[i])
}
} else {
var tarName = document.getElementsByTagName(selector)
for (i in tarName) {
elementArr.push(tarName[i])
}
}
}
return elementArr;
}
// 将局部域开放给全局作用域
global.$$ = global.woQuery = woQuery
})(typeof window !== 'undefined' ? window : this);
通过 HTML 验证此代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test woQuery</title>
<script src="./15 模拟 jQuery 的工厂函数以及选择器用法.js"></script>
</head>
<body>
<button id="btn"></button>
<button class="cls"></button>
<script>
console.log($$('#btn'));
console.log($$('.cls'));
console.log($$('button'));
</script>
</body>
</html>
此代码的执行结果如下所示