熟悉 jQuery






4.86/5 (95投票s)
以有趣简单的方式学习 jQuery(希望如此)。
目录
- 背景
- 引言
- jQuery 的解剖
- 设置 jQuery ready 处理程序
- 快速演示
- 深入研究 jQuery
- CSS 选择器
- XPath 选择器
- 属性选择器 (*更新)
- 表单选择器
- 自定义选择器
- DOM
- 事件处理
- 效果和动画
- 使用 Ajax 为网站增色
- 生成自动目录
- 限制文本框输入
- 创建自己的自定义过滤器
- 使用插件 API
- 最佳实践
- 构建一个简易幻灯片应用 (*新)
- 构建一个树视图插件 (*新)
- 参考文献
- 历史
背景
本文是我在通过各种书籍和网站学习 jQuery 过程中收集的笔记的总结。因此,它仍处于 WIP 阶段,并将根据我对这个优秀库的理解和研究进行更新,并会添加 jQuery 在 asp.net/mvc 中的简单用例。
引言
jQuery 是一个 JavaScript 库,它拥有丰富的 API,用于 DOM 操作、事件处理、动画和 Ajax 交互。以下是 jQuery 吸引客户端脚本编程的主要特点。
- jQuery 跨浏览器
- jQuery 支持 Ajax
- 丰富的选择器
- DOM 操作
- 动画
- 丰富的 UI
jQuery 的解剖
jQuery 架构围绕以下领域展开。
设置 jQuery ready 处理程序
jQuery 允许您在页面元素加载后运行代码。这比浏览器 onload() 函数更有效,后者仅在所有图像加载后才被调用。要在页面准备就绪时运行代码,请使用以下语法
$(document).ready(function() { .... }); There's a shorthand as well $(function() { .... });
快速演示
让我们快速浏览一下 jQuery 的实际应用。
按 ID 选择页面元素
$('#id') 用于按 ID 选择元素。当您单击“条纹”按钮时,将触发 stripe() JS 方法,该方法会切换 ID 为“third”的元素的类。随后的点击将重置样式。
代码和标记如下所示。
<head>
<title>Select a paragraph</title>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript">
function stripe( )
{
$('#third').toggleClass('striped');
}
</script>
<style>
p.striped {
background-color: cyan;
}
</style>
</head>
<body>
<h1>Select a paragraph</h1>
<div>
<p>This is paragraph 1.</p>
<p>This is paragraph 2.</p>
<p id="third">This is paragraph 3.</p>
<p>This is paragraph 4.</p>
</div>
<form>
<input type = "button" value="Stripe" onclick="stripe()"> </input>
</form>
</body>
选择一组元素
$("div") 选择所有 div 元素。fadeIn() 效果应用于每个匹配的 div。
div 最初是隐藏的。
单击按钮后,所有 div 元素缓慢淡入。
代码和标记如下所示。
<head>
<title>Selecting a set of Elements</title>
<script type="text/javascript" src="Scripts/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
function fade() {
$("div").fadeIn('slow');
}
</script>
</head>
<body>
<h1>Fade</h1>
<div style ="display:none">
This div was hidden.
</div>
<div style ="display:none;border:solid 1px orange">
So as this.
</div>
<form>
<input type = "button" value="Fade Div" onclick="fade()" />
</form>
</body>
按样式选择元素
$(p.mark) 选择所有带有 "mark" 类的段落元素。
代码和标记如下所示。
<head>
<title>Select a paragraph</title>
<script type="text/javascript" src="Scripts/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
function highlight() {
$('p.mark').toggleClass("highlight");
}
</script>
<style type="text/css">
p.mark {
font-weight: normal;
}
p.highlight {
background-color: lightgray;
}
</style>
</head>
<body> <h1>Select a paragraph</h1> <div> <p class = "mark">This is paragraph 1.</p> <p>This is paragraph 2.</p> <p class = "mark">This is paragraph 3.</p> <p>This is paragraph 4.</p> </div> <input type = "button" value="Highlight" onclick="highlight()"/> </body>
深入研究 jQuery
上述讨论总结了 jQuery 的非常基础的知识。下一节将根据所概述的解剖结构深入探讨 jQuery。
CSS 选择器
CSS 选择器基于 w3C 概述的 CSS 1-3。有关更多信息,请访问 w3.org
按元素选择
所有元素选择的形式为 $('T'),其中 'T' 代表元素标签名称。
例如:
- $('div') 选择文档中所有标签名为 div 的元素
- $('input') 选择文档中所有标签名为 input 的元素。
jQuery 使用 JavaScript 的 getElementsByTagName() 函数进行标签名选择器。
按 ID 选择
这采取了形式 $('#id'),其中 ID 等于 id。
例如:
- $('#firstName') 选择 id = 'firstName' 的唯一元素。
- $('div#main') 选择 id 为 'main' 的单个 div。
如果存在多个具有相同 id 的元素,jQuery 将选择 DOM 中第一个匹配的元素。
按类选择
这采用的形式是 $('.myclass'),其中 class 等于 myclass。
例如:
- $('.blink') 选择所有 class='blink' 的元素。
- $('p.blink') 选择所有带有 blink 类的段落。
- $('.mybold.myblink') 选择所有同时具有 'mybold' 和 'myblink' 类的元素。
从性能角度来看,示例2更可取,因为它将查询限制在给定的标签名。
按后代选择 (E1 E2)
匹配所有 E1 匹配元素的后代中与 E2 匹配的元素。
例如:
- $('#menu li') 选择所有 ID 为 menu 的元素的后代中与 <li> 匹配的元素。
- $('a img') 选择所有与 <a> 匹配的元素的后代中与 <img> 匹配的元素
元素的后代是该元素的任何子元素、孙子元素等等。
<div id = "menu"> <div id = "item1"> <div id = "item-1.1"> <div id = "item-1.2"> <div id = "item-1.2.1"/> </div> </div> </div>
在上面的例子中,“item-1.2.1”是“item-1.2”、“item-1.1”、“item1”和“menu”的后代。
选择子元素 (E1 > E2)
匹配所有 E1 匹配元素的子元素中与 E2 匹配的元素。
例如:
- $('li > ul') 选择所有与 <li> 匹配的元素的子元素中与 <ul> 匹配的元素。
- $('p > pre') 匹配所有与 <p> 匹配的元素的子元素中与 pre 匹配的元素。
除了IE 6及以下版本,子选择器在所有现代浏览器中都有效。子组合器是后代组合器的更具体形式,因为它只选择第一级后代。
组合器,因为它只选择第一级后代。
相邻兄弟 (E1 + E2)
匹配所有紧跟在 E1 匹配元素之后且与 E1 匹配元素具有相同父级的 E2 匹配元素。
例如:
- $('p + img') 选择所有紧跟在兄弟元素 <p> 之后与 <img> 匹配的元素。
+ 组合器只选择兄弟元素,即与匹配元素处于同一级别的元素。
一般兄弟 (E1 ~ E2)
匹配所有 E2 元素,这些元素位于 E1 匹配元素之后,且与 E1 匹配元素具有相同的父元素。
例如:
- $('p ~ img') 选择所有与 <p> 匹配的兄弟元素之后与 <img> 匹配的元素。
+ 和 ~ 之间的区别是,+ 组合器只作用于紧随其后的兄弟元素,而 ~ 组合器将其作用范围扩展到所有后续的兄弟元素。
考虑以下 HTML。
<ul> <li class = "1st"></li> <li class = "2nd"></li> <li class = "3rd"></li> </ul> <ul> <li class = "4th"></li> <li class = "5th"></li> <li class = "6th"></li> </ul>
$('li.1st ~ li') 选择 <li class = "2nd"> 和 <li class = "3rd">。
$(li.1st + li) 选择 <li class = "2nd">
多个元素 (E1, E2, E3)
选择所有与选择器 E1、E2 或 E3 匹配的元素。
例如:
- $('div, p, pre') 选择所有与 <div>、<p> 或 <pre> 匹配的元素。
- $('p bold, .class-name') 选择所有作为 <p> 后代并与 <bold> 匹配的元素,以及所有具有 '.class-name' 类的元素。
逗号 (,) 组合器是一种选择不同元素的有效方式。
第 N 个子元素 (:nth-child(n))
所有作为其父元素的第 n 个子元素的元素。
例如:
- $('li:nth-child(3)') 选择所有与 <li> 匹配且是其父元素第三个子元素的元素。
这里的“n”是从1开始的,因为它严格遵循CSS规范。对于所有其他选择器,jQuery 遵循0开始的计数。
第一个子元素 (:first-child)
所有作为其父元素的第一个子元素的元素。
例如:
- $('li:first-child') 选择所有与 <li> 匹配且是其父元素的第一个子元素的元素。
:first-child 伪类是 :nth-child(1) 的简写。
最后一个子元素 (:last-child)
所有作为其父元素的最后一个子元素的元素。
例如:
- $('li:last-child') 选择所有与 <li> 匹配且是其父元素的最后一个子元素的元素。
唯一的子元素 (:only-child)
所有作为其父元素唯一子元素的元素。
例如:
- $(':only-child') 选择所有作为其父元素唯一子元素的元素。
- $('p:only-child') 选择所有与 <p> 匹配且是其父元素的唯一子元素的元素。
非 (:not(s))
所有不匹配选择器 's' 的元素。
例如:
- $('li:not (.myclass)') 选择所有与 <li> 匹配且不具有 class="myclass" 的元素。
- $('li:not(:last-child)') 选择所有与 <li> 匹配且不是其父元素的最后一个子元素的元素。
空 (:empty)
所有没有子元素(包括文本节点)的元素。
例如:
- $('p:empty') 选择所有与 <p> 匹配且没有子元素的元素。
- $('empty') 选择所有没有子元素的元素。
所有元素 (*)
所有元素
例如:
- $('*') 选择文档中的所有元素。
- $(p > '*') 选择所有作为段落元素的子元素的元素。
XPath 选择器
所有包含由 E 匹配的元素的元素。
例如:
- $('div[p]') 选择所有与 <div> 匹配且包含与 <p> 匹配的元素的元素。
此选择器类似于后代选择器(E1 // E2 或 E1 E2)的反向,因为它选择所有具有由 E1 匹配的后代元素的元素,而不是所有与 E2 匹配且是其他元素后代的元素。
属性选择器
在 jQuery 1.3 之前,属性选择器以 @ 符号开头。在 V1.3 之后,删除属性名称前的 @ 符号。
具有属性 ([foo])
所有具有 foo 属性的元素。
例如:
- $('a[rel]') 选择所有与 <a> 匹配且具有 rel 属性的元素。
- $('div[class]') 选择所有与 <div> 匹配且具有 class 属性的元素。
属性值等于 ([foo=bar])
所有具有 foo 属性且其值严格等于 bar 的元素。
例如:
- $('a[rel=nofollow]') 选择所有与 <a> 匹配且具有属性 'rel',其值为 'nofollow' 的元素。
- $('input[name=first-name]') 选择所有与 <input> 匹配且具有名称值严格等于 first-name 的元素。
属性值不等于 ([foo != bar])
所有不具有 foo 属性且其值严格等于 bar 的元素。
例如:
- $('a[rel != nofollow]') 选择所有与 <a> 匹配且不具有属性 'rel',其值为 'nofollow' 的元素。
- $('input[name != first-name]') 选择所有与 <input> 匹配且不具有名称属性,其值严格等于 first-name 的元素。
注意:这些选择器将属性值视为单个字符串。因此,带有空格分隔值的属性将不被匹配。
要排除以下匹配 <a rel="nofollow self" href=...>link</a>,请使用以下选择器
$('a:not[rel *= nofollow])')。
表单选择器
以下是表单选择器列表
- :input -> 选择所有表单元素 (input, select, textarea, button)。
- :text -> 选择所有文本字段 (type = "text")
- :password -> 选择所有密码字段 (type = "password")
- :radio -> 选择所有单选字段 (type = "radio")
- :checkbox -> 选择所有复选框字段 (type = "checkbox")
- :submit -> 选择所有提交按钮 (type = "submit")
- :image -> 选择所有表单图片 (type = "image")
- :reset -> 选择所有重置按钮 (type = "reset")
- :button -> 选择所有其他按钮 (type = "button")
- :file -> 选择所有 <input type = "file">
自定义选择器
偶数元素 (:even) 奇数元素 (:odd)
:even 所有偶数索引的元素
:odd 所有奇数索引的元素
例如:
- $('li:even') 选择所有与 <li> 匹配且具有偶数索引值的元素。
- $('tr:odd') 选择所有与 <tr> 匹配且具有奇数索引值的元素。
由于 :even 和 :odd 伪类是根据其索引匹配元素的,它们使用 JS 原生的零基编号。因此,:even 选择第一个、第三个(依此类推)元素,而 :odd 选择第二个、第四个(依此类推)元素。
第 N 个元素 (:eq(n), :nth(n))
索引值等于 n 的元素。
例如:
- $('li:eq(2)') 选择第三个 <li> 元素
- $('p:nth(1)') 选择第二个 <p> 元素。
大于 (:gt(n))
索引大于 N 的元素。
例如:
- $('li:gt(1)') 选择第二个 <li> 元素之后的所有 <li> 匹配元素。
小于 (:lt(n))
索引值小于 n 的元素。
例如:
- $('li:lt(3)') 选择第四个 <li> 元素之前的所有 <li> 匹配元素,换句话说,是前三个 <li> 元素。
第一个 (:first)
元素的第一个实例。
例如:
- $('li:first') 选择第一个 <li> 元素。
- $('tr:first') 选择第一个 <tr> 元素。
最后一个 (:last)
元素的最后一个实例。
例如:
- $('li:last') 选择最后一个 <li> 元素。
- $('tr:last') 选择最后一个 <tr> 元素。
父元素 (:parent)
所有是另一个元素(包括文本节点)父元素的元素。
例如:
- $(':parent') 选择所有是另一个元素父元素的元素。
- $('td:parent') 选择所有与 <td> 匹配且是另一个元素父元素的元素。
包含 (:contains(text))
所有包含指定文本的元素。
例如:
- $('div:contains(sample div)') 选择所有与 <div> 匹配且包含文本 'sample div' 的元素。
- $('li:contains(wrong link)') 选择所有与 <li> 匹配且包含文本 'wrong link' 的元素。
匹配文本可以出现在选择器元素中,也可以出现在该元素的任何后代中。
可见 (:visible)
所有可见元素。
例如:
- $('div:visible') 选择所有与 <div> 匹配且可见的元素。
:visible 选择器包括 display 为 block 或 inline 或任何其他值(除了 none),且 visibility 为 visible 的元素。
隐藏 (:hidden)
所有隐藏的元素。
例如:
- $('div:hidden') 选择所有与 <div> 匹配且隐藏的元素。
DOM
jQuery 拥有强大的 jQuery 遍历和操作方法。
$() 工厂函数再访
我们已经使用 $() 函数来访问文档中的元素。让我们卷起袖子,尝试用 $() 玩一些花样。实际上,只需在括号内插入一小段 HTML 代码,我们就可以创建一个全新的 DOM 结构。这不是很神奇吗?
插入新元素
以下是 jQuery 用于将元素插入/追加到 DOM 中的方法。
.before(content)
在匹配元素集合中的每个元素之前插入由参数指定的内容。返回值是用于链式调用的 jQuery 对象。考虑以下 HTML 片段。
<div class = "div1"> This div already exist </div>
执行以下 jQuery 脚本。
$('div.div1').before('<div class="insert">This div is dynamically inserted</div>')
生成的 HTML 将是
<div class = "insert"> This div is dynamically inserted </div> <div class = "div1"> This div already exist </div>
.insertBefore(content)
在参数中指定的元素集之前插入匹配元素集中的每个元素。考虑以下 HTML 片段。
<div class = "div1"> This div already exist </div>
执行以下 jQuery 脚本。
$('<div class="insert">This div is dynamically inserted</div>').insertBefore('div.div1')
生成的 HTML 将是
<div class = "insert"> This div is dynamically inserted </div> <div class = "div1"> This div already exist </div>
这两种函数的工作方式只有结构上的差异。
.after(content)
在匹配元素集合中的每个元素之后插入由参数指定的内容。考虑以下 HTML 片段。
<div class = "div1"> This div already exist </div>
执行以下 jQuery 脚本。
$('div.div1').after('<div class="insert">This div is dynamically inserted</div>')
生成的 HTML 将是
<div class = "div1"> This div already exist </div> <div class = "insert"> This div is dynamically inserted </div>
.insertAfter(content)
将匹配元素集合中的每个元素插入到参数中指定的元素集合之后。考虑以下 HTML 片段。
<div class = "div1"> This div already exist </div>
执行以下 jQuery 脚本。
$('<div class="insert">This div is dynamically inserted</div>').insertAfter('div.div1');
生成的 HTML 将是
<div class = "div1"> This div already exist </div> <div class = "insert"> This div is dynamically inserted </div>
事件处理
即将推出
效果和动画
即将推出
用 Ajax 丰富网站
让我们从一个小的用例开始。假设您有一个用例,需要向博客文章添加“评论”。代码片段是为 ASP.NET MVC 框架编写的,但应该可以无缝地修改它以适应经典 asp.net、php、ror 或您认为合适的任何其他框架。
评论视图非常简单。以下是用于添加评论的最少标记,没有任何样式。
<h2>Add Comment</h2> <label for ="body">Body</label> <br /> <%= Html.TextArea("body")%> <div id = "loading-panel"></div> <hr /> <input id="comment_submit" type="button" value = "Publish" />
控制器的最小代码如下所示。当单击“发布”按钮时,我们希望以异步方式向 PostController 的名为“NewComment”的操作方法发出请求。此处显示的代码仅用于演示目的,因此除了本讨论的上下文之外,没有任何意义。
public class PostController : BaseController { /// Add new comment /// <param name="postId">The post id.</param> /// <param name="body">The body.</param> public ActionResult NewComment(Guid postId, string body) { var post = Repository.GetPostById(postId); var comment = new Comment { Body = body, Post = post }; Repository.AddComment(comment); return Content(body); } }
让我们设置 jQuery 以异步方式回发并同时显示进度条。
<script type="text/javascript"> function flashit() { flash('#comment-list li:last'); } function flash(selector) { $(selector).fadeOut('slow').fadeIn('show'); } </script><script type = "text/javascript"> $(function() { $("#comment_submit").click(function() { // Set up a string to POST parameters. You can create the JSON string as well. var dataString = "postId=" + "<%=Model.Post.Id %>" + "&body=" + $('#body').val(); (01) $.ajax({ (02) type: "POST", (03) url: "/Post/NewComment", (04) data: dataString, (05) beforeSend: function(XMLHttpRequest) { (06) $('#loading-panel').empty().html('<img src="https://codeproject.org.cn/Content/Images/ajax-loader.gif" />'); (07) }, success: function(msg) { (08) $('#comment-list').append('<li>' + msg + '</li>'); (09) flashit(); (10) }, error: function(msg) { (11) $('#comment-list').append(msg); }, complete: function(XMLHttpRequest, textStatus) { (12) $('#loading-panel').empty(); (13) } }); }); }); </script>
在上面的代码中,jQuery 工厂函数 $() 设置了 "comment_submit" 点击事件处理程序。每当点击 "submit" 按钮时,上面定义的点击函数就会执行。以下几点强调了上面函数中发生的事情。
- 第 01 行设置要发布到控制器的数据。
- 第 02 行调用 ajax 方法,并带有以下参数。
- 第 03 行将请求类型设置为 "POST"。
- 第 04 行设置 URL。在这种情况下,应该调用 Post Controller 的操作方法。
- 第 05 行将数据作为请求的一部分进行分配。
- 第 06 行设置 beforeSend() 处理程序。此方法在 ajax 方法被调用之前执行。
- 第 07 行设置加载面板以显示加载图像。该图像可从 http://www.ajaxload.info/ 下载。
- 第 08 行设置 success() 处理程序。如果 AJAX 请求成功执行,则执行此方法。
- 第 09 行如果请求成功执行,则将新消息附加到 comment-list div。
- 第 10 行调用 flashit() 方法,该方法会闪烁/动画插入的方法。
- 第 11 行设置 error() 处理程序。如果在执行 AJAX 请求时出现任何错误,则执行此方法。
- 第 12 行设置 complete() 处理程序。此方法在 AJAX 请求完成后执行。
- 第 13 行清空加载面板以清除图像。
AJAX 选项
即将推出。
生成自动目录
让我们快速为我们的页面创建一个自动目录。假设我们有一个具有以下结构的页面,并且我们需要基于 <h3> 标题创建一个目录。我们希望将此目录插入到“header”div 中。所有目录内容都应链接回页面内容。
HTML 片段
<div id="header"> <h1> Automatic Bookmark Headings Example</h1> <h2> Using jQuery to Extract Existing Page Information</h2> </div> <div id="Div1"> <h1> Automatic Bookmark TOC Example</h1> <h2> Using jQuery to Extract Existing Page Information</h2> </div> <div id="Div2"> <h3>Introduction</h3> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> <a href="#header" title="return to the top of the page">Back to top</a> </div> <div id="content"> <h3>Content</h3> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> <a href="#header" title="return to the top of the page">Back to top</a> </div>
TOC 生成器脚本
<script type="text/javascript"> $("document").ready(function() { createTOC('h3', 'header'); }); // tag : the header tag for which the toc is to be built // container : id of the div that we want to append the resulting TOC. function createTOC(tag, container) { var anchorCount = 0; // count to create unique id // create an unordered list var oList = $("<ul id='bookmarksList'>"); /* 1. For each header tag create a named anchor and insert the into header tag. It will serve as the jump location for the TOC. 2. Add the link to the unordered list that will point to the named anchor. */ /* Get all h3 inside div where id is not equal to header. // For each h3 tag // 1. Create the named anchor. This should be a unique name. // 2. Set the html for h3 tag to a named anchor. // 3. Add the existing html for the h3 in front of the named anchor. // 4. Create the TOC links // 5. Add the TOC to the container. */ $("div:not([id=header]) " + tag).each(function() { $(this).html("<a name='bookmark" + anchorCount + "'></a>" + $(this).html()); oList.append($("<li><a href='#bookmark" + anchorCount++ + "'>" + $(this).text() + "</a></li>")); }); $("#" + container).append(oList); } </script>
这是该片段运行时的截图
我认为代码注释得很好,足以理解其逻辑。
限制文本框输入
让我们快速了解一下如何限制文本框的输入,并显示剩余可输入的字符数。
<script type="text/javascript"> $(function() { var limit = 250; $('#dvLimit').text('250 characters left'); $('textarea[id$=txtDemoLimit]').keyup(function() { var len = $(this).val().length; if (len > limit) { this.value = this.value.substring(0, limit); } $("#dvLimit").text(limit - len + " characters left"); }); }); </script>
$() 函数在启动时执行以下操作。
1. 将变量设置为 250 个字符的限制。
2. 为 id 为 "dvLimit" 的 "div" 元素分配默认值。
3. 查找包含 id "txtDemoLimit" 的控件并挂接 keyup 事件。
4. 在 keyup 事件中获取当前文本的长度。
5. 如果长度大于设置的限制,则将文本值设置为指定限制内的子字符串。
6. 更新 div 中剩余可输入的字符数。
HTML 如下所示。
<div id="dvLimit"></div> <div> <asp:TextBox ID="txtDemoLimit" TextMode="MultiLine" Columns = "40" Rows = "10" runat="server"></asp:TextBox> </div>
以下是应用程序的运行情况。
创建自己的自定义过滤器 (*新)
您可以创建自己的自定义过滤器,与 jQuery 选择器一起使用。这提供了一种扩展 jQuery 的好方法。
让我们创建自己的自定义过滤器 ":inline",它返回所有 display 设置为 "inline" 的元素。
(function ($) { // Define the custom filter by extending $.expr[':'] $.expr[':'].inline = function(elem) { return $(elem).css('display') === 'inline'; }; })(jQuery);
上面的过滤器返回所有 display 样式设置为“inline”的元素。还有其他方法或方式可以获取这些信息,但过滤器似乎使整个体验非常流畅。
创建上述过滤器的替代方法。
// This syntax allows you to add multiple filters at one go... $.extend( jQuery.expr.filters, { inline: function(elem) { return $(elem).css('display') === 'inline'; } } );
如果您查看 jQuery 源代码,您会发现 "jQuery.expr.filters" 只是 jQuery.expr[":"] 的别名。以下是代码片段供参考。
jQuery.expr[":"] = jQuery.expr.filters;
我第一次读到这篇文章是在 Dissecting jQuery filters
希望您能创造性地扩展 jQuery 过滤器并分享您的想法。
使用插件 API
即将推出
最佳实践
您可能已经知道,使用 jQuery 的方法不止一种,我们必须尝试使用最好的方法,即性能最高的方法。以下是您可以从 jQuery 中获得最大性能的一些方法。请注意,我没有考虑浏览器、操作系统、硬件以及可能对性能产生影响的其他因素
-
最新版本
获取最新版本的 jQuery。由于 jQuery 正在积极开发中,每个版本都会有很多修复。
-
背景
向 jQuery 函数传递上下文可以提高查询性能,因为这将减少遍历的 DOM 元素的数量。为此,您需要向 jQuery 函数传递一个第二个参数,该参数引用一个 DOM 元素。然后,此元素将用作 DOM 查询的起点,因此应用程序可能会获得一些性能优势。
在许多情况下,您可以将 _this_ 作为第二个参数。请注意,为了获得性能提升,您需要将实际的 DOM 引用作为第二个参数传递。传递除 DOM 引用之外的任何内容仍然需要搜索整个文档,实际上可能会阻碍性能。
-
选择器性能
这是您需要做出的重要设计决策之一。性能可能直接受您使用的选择器影响。选择器性能取决于以下几点:- 选择器表达式的复杂性
- 选择器类型
- 正在评估的 DOM 的大小和复杂性
以下是使用 jQuery 时可以考虑的一些重要点
- 尽可能优先使用 ID 选择器。
- 选择器越简单,性能越好
- 如果必须使用类名,请务必尝试将其与其他选择器一起使用。
例如,根据您的需求使用 $('div.menu') 而不是 $('.menu') 或类似的东西。 - 由于简单的 DOM 遍历速度更快,上下文变得更加重要。
-
如果元素经常使用,请缓存它们
切勿为相同的元素重复 DOM 查询。缓存结果集并使用它。当您处理循环时,这更重要。将包装集存储在循环外部的局部变量中,以避免在每次迭代期间进行查询。 -
将 DOM 更改降至最低
与上一个提示一样,此概念在处理循环时很重要。避免在循环中更新元素。相反,在循环中创建元素的字符串表示形式并在循环外部更新 DOM。// This code is slow var list = $('div'); for (i = 1; i <= 1000; i++) { list.append('Menu ' + i ); // interacts with the DOM 1000 times } // This code is a bit faster var list2 = $('div'); var items = ''; for (i = 1; i <= 100; i++) { items += 'Menu ' + i ; // string concatenation } list2.html(items); // Use DOM only once. NOTE: string concatenation is slow but in this case it will be faster comparted to DOM manipulation. Also there are various optimized string library that peforms efficient concatenation.
-
尽可能使用多个选择器
Prefer $('#p1, #p2').hide(); Rather than $('#p1').hide(); $('#p2').hide();
-
利用链式调用
在有意义时使用 jQuery 链式调用。它提高了代码性能并避免了不必要的重复。
更多内容即将推出....
根据您的需求修改并享受 jQuery 的乐趣!!!
构建一个简易幻灯片应用
本次更新,让我们构建一个简单的幻灯片应用。我们将保持 API 简单易懂,并且可能会为了便于理解而跳过某些最佳实践。但我会根据我对推荐实践的观察来更新文章,并可能会更改示例以提及这些实践。
让我们从头开始。这是供您参考的 HTML 标记。plunkr 上有一个实时演示,网址为 http://plnkr.co/edit/OCnBecXAfhXAKbQExW2v?p=info
这是我们将要构建的内容的预览。
我将 CSS 保持简单,因为我不想让本文偏离主题。添加 jQuery 和 jQuery UI 的最新引用(我们将使用 jQuery UI 来显示对话框)
<body> <div id="board"></div> </body>
首先,让我们构建幻灯片模块的 API。这将使我们能够了解如何设计我们的库。
$(function () { mySlideShow.title("Build your own slide object V0.1",{elementId: "board", timer: 0}) .slide({ title: "Slide 1", points: ["Point 1","Point 2", "Point 3", "Point 4","Point 5", "Point 6" ] }) .slide({ title: "Slide 2", points: ["Point 3","Point 2"] }) .slide({ title: "Slide 3", points: ["Point 3","Point 3"] }) .slide({ title: "Slide 4", points: ["Point 4","Point 4"] }) .show(); });
我们尚未编写 mySlideShow 对象。但让我们看看我们对这个对象的期望。我们打算通过传入标题、将显示幻灯片的 **elementID** 以及 **计时器** 值来调用幻灯片。如果计时器值为 0,则可以通过单击“next”和“prev”按钮来导航幻灯片。计时器值以毫秒为单位。如果您设置计时器值为 1000,则在 1000 秒后,幻灯片将自动更改。
**注意**:这不是一个功能齐全的库,但它包含足够的信息来涵盖基本原理。您可以根据您的要求进行调整,按照您喜欢的方式进行样式设置,添加图像等。
**注意**:此外,请注意此代码仅经过几次迭代,因此我了解一些优化方法。本文可能会在将来更新,但现在的想法是让 MVP(最小可行产品)功能准备就绪 :)。
请注意,这里的函数是链式调用的。我们可以通过使用 slide() 方法来指定幻灯片和幻灯片中的点,该方法接受一个带有标题和点数组的对象字面量。
现在让我们看看这个库/模块是如何编码的。首先,我们将整个库代码封装在一个 IIFE(立即调用函数,也称为自调用匿名函数)中。**请注意,我们明确地将全局对象(如 window 和 jQuery)传递给函数调用(这是避免模块/命名冲突的最佳实践)**
(function (window, $) { var mySlideShow = { }; window.mySlideShow = mySlideShow; })(window, jQuery);
这是带有详细注释的完整源代码。如果代码的任何部分不清楚,请在下面的评论中告诉我。我将添加更多这样的小例子。
(function (window, $) { var mySlideShow = { $element: null, counter: 0, // tracks which slide is currently selected slides: [], // holds all slide object // The text to show in the title and the options object which contain // the elementID and the timer value. title: function (text, options){ var elementId = options.elementId; this.timer = options.timer; this.$element = $("#" + elementId); // This will be displayed in the jquery UI dialog this.$element.attr("title", text); // Create the container and the footer divs this.$element.append("<div class='container'></div>"); this.$element.append("<div class='footer'></div>"); var $footer = $(".footer", this.$element); // Add the next and prev button to the footer div $footer.append("<input type='button' class='prev' value='prev'>"); $footer.append("<input type='button' class='next' value='next'>"); // Create the div for holding the slides $(".container").append("<div class='slides'></div>"); // Call the initialize method this.onInit(); // Setup the event handler. NOTE: The repetation in the handlers can be // refactored later. this._next(); // setup next button click this._prev(); return this; // for method chaining }, /* In the initialize method setup the timer and handle the windows resize event, so that as the window is resized the slides takes up the full screen. */ onInit: function () { // Store a reference to the original object as otherwise in in time calls like // setInterval the context will change and "this" will point to global object. var that = this; if (that.timer) { setInterval(function(){ that.next(); },that.timer); } $(window).resize(function () { $(that.$element).css({ 'width': $(window).width(), 'height': $(window).height(), 'left': '0px', 'top':'0px' }); }).resize(); //<---- resizes on page ready }, /* Given the index of the slide, show the slide. */ load: function (index) { //loads the slide based on index var that = this; var current = that.slides[index]; var $slides = $("div.slides"); $slides.html(""); // clear $slides.append("<h2>" + current.title + "</h2>"); for(var i = 0; i < current.points.length; i++) { $slides.hide().append("<li>" + current.points[i] + "</li>").slideDown(); // lets animate } }, /* Move to next slide. */ next: function () { var that = this; that.counter ++; if (that.counter >= that.slides.length) { that.counter = 0; // reset the counter if on last slide. } that.load(that.counter); // load the slide }, /* Move to prev slide. */ prev: function () { var that = this; that.counter --; if (that.counter < 0) { that.counter = 0; // reset the counter, if first slide reached. } that.load(that.counter); // load the slide }, // Event handler to track the click of next button _next: function () { var that = this; $(".next").on("click", function (e) { that.next(); }) }, // Event handler to track the click of prev button _prev: function () { var that = this; $(".prev").on("click", function (e) { that.prev(); }) }, /* Create the array for storing slide objects */ slide: function (options) { this.slides.push(options); return this; // for method chaining }, /* Show the lide first time, by invoking the jQuery UI modal dialog. */ show: function () { this.load(0); // load the first slide this.$element.dialog({ height: $(window).height()-10, width: $(window).width()-10, modal: true }); } }; window.mySlideShow = mySlideShow; })(window, jQuery);
以下是一些屏幕截图,附有代码和幻灯片演示的指针。
PS:我肯定计划根据最新变化更新、添加、审查和更正内容。
构建树视图插件
假设您有以下无序列表数据,需要将其渲染为树视图。
<div class="tree"> <ul> <li><a>First Level</a> <ul> <li><a>Second Level</a></li> <li><a>Second Level</a></li> <li><a>Second Level</a></li> </ul> </li> <li><a>First Level</a> <ul> <li><a>Second Level</a> <ul> <li><a>Third Level</a></li> <li><a>Third Level</a></li> <li><a>Third Level</a> <ul> <li><a>Fourth Level</a></li> <li><a>Fourth Level</a></li> <li><a>Fourth Level</a> <ul> <li><a>Fifth Level</a></li> <li><a>Fifth Level</a></li> <li><a>Fifth Level</a></li> </ul> </li> </ul> </li> </ul> </li> <li><a>Second Level</a></li> </ul> </li> <li><a>First Level</a> <ul> <li><a>Second Level</a></li> <li><a>Second Level</a></li> </ul> </li> </ul> </div>
我们希望如下所示调用我们的自定义 jQuery 插件。
<script> $(function() { $(".tree").quickTree({ onNodeClick: onclick }); }) function onclick(el) { console.log(el); } </script>
我们将创建一个名为 "quickTree" 的 jquery 插件,它可以应用于任何现有元素。对于此示例,我将其与无序列表配合使用,但您可以修改代码以适应您的要求,添加图像、标签等。
jquery 插件的代码如下所示,并共享了可用的 plnkr 网址
(function( $ ) { $.fn.quickTree = function(options) { // Establish our default settings var settings = $.extend({ color : "#ddffdd", }, options); return this.each(function() { var ele = $(this); $(ele).find('li' ).each( function() { if( $( this ).children( 'ul' ).length > 0 ) { $( this ).addClass( 'parent' ); } }); $(ele).find('li > a' ).click( function( ) { if ($(this).parent().hasClass("parent")) { $( this ).parent().toggleClass( 'active' ); $( this ).parent().children( 'ul' ).slideToggle( 'fast' ); } if (settings.onNodeClick){ settings.onNodeClick(this); } }); }); }; }( jQuery ));
可用网址在此处 jQuery Treeview demo
历史
- 2018年3月12日- 添加了 jquery 自定义树视图插件(解释待定)
- 2016年12月18日- 添加了关于属性选择器的说明。jQuery 1.3 版本之后不再需要 @ 符号。
- 2016年12月16日 - 添加了幻灯片模块示例
- 2010年8月31日 - 创建您自己的自定义过滤器
- 2010年5月22日 - 性能最佳实践。
- 2009年12月06日 - 限制文本输入。
- 2009年9月15日 - 生成自动目录。
- 2009年8月24日 - 添加了一个简单的 AJAX 用例。
- 2009年8月23日 - 创建了文章的第一个版本。