jQuery 教程
jQuery 是一个快速、小巧、功能丰富的 JavaScript 库,让 HTML 文档操作、事件处理、动画和 AJAX 变得简单。它用一句话概括:"Write less, do more"(写得更少,做得更多)。
jQuery 能做什么
| 能力 | 说明 |
|---|---|
| DOM 操作 | 选择、创建、修改元素 |
| 事件处理 | 点击、键盘、表单事件 |
| 动画效果 | 隐藏、淡入淡出、滑动、自定义动画 |
| AJAX | 无刷新加载数据 |
| 插件生态 | 丰富的第三方插件 |
jQuery 简介
jQuery 由 John Resig 于 2006 年创建,目标是解决浏览器兼容性问题,统一 DOM 操作 API。2019 年 jQuery 3.x 依然是使用最广泛的 JS 库之一。
核心思想
| 思想 | 说明 |
|---|---|
| 选择器驱动 | 用 CSS 选择器选中元素 |
| 链式调用 | 一个操作接一个操作 |
| 隐式迭代 | 选中多个元素自动遍历 |
| 统一 API | 屏蔽浏览器差异 |
// 原生 JS
document.querySelectorAll('.item').forEach(function(el) {
el.style.display = 'none';
});
// jQuery:一行搞定
$('.item').hide();$ 或 jQuery 为前缀,$() 等价于 jQuery()。jQuery 安装
jQuery 安装有两种方式:
CDN 引入(推荐)
<!-- 官方 CDN -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- 国内常用 CDN(bootcdn) -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- 在 body 结束前引入,或用 defer -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js" defer></script>本地下载
# 下载到本地项目
# https://jquery.com/download/
# 保存为 js/jquery.min.js
<script src="js/jquery.min.js"></script>$ 未定义会报错。jQuery 语法
jQuery 语法基础:
// 核心语法
// $(选择器).动作()
// 文档就绪(页面加载完成后再执行)
$(document).ready(function() {
console.log("页面已加载");
});
// 简写
$(function() {
console.log("页面已加载");
});
// 选择元素并隐藏
$("p").hide();
// 链式调用
$("#box").css("color", "red").slideUp(500).slideDown(500);
// $ 与 jQuery 等价
jQuery("#box").hide();
$(document).ready === jQuery(document).ready; // true$(function(){ ... }) 中,确保 DOM 就绪后再操作,这是 jQuery 标准写法。jQuery 选择器
jQuery 选择器:基于 CSS 选择器,功能强大:
// 基本选择器
$("#id") // ID
$(".class") // 类
$("p") // 标签
$("*") // 全部
$("p.intro") // 标签+类
$("p, div") // 多选
// 层级选择器
$("div p") // 后代
$("div > p") // 直接子元素
$("div + p") // 相邻兄弟
$("div ~ p") // 后续兄弟
// 属性选择器
$("[href]") // 有 href
$("a[target='_blank']") // 属性值
$("input[type='text']") // 表单元素
$("[href^='https']") // 以 https 开头
$("[href$='.pdf']") // 以 .pdf 结尾
$("[href*='example']") // 包含 example
// 表单选择器
$(":input") // 所有输入元素
$(":checked") // 选中的
$(":selected") // 选中的下拉
$(":disabled") // 禁用
// 过滤
$("p:first") // 第一个 p
$("p:last") // 最后一个
$("li:even") // 偶数索引
$("li:odd") // 奇数索引
$("li:eq(2)") // 索引 2
$("li:gt(2)") // 大于索引 2
$("li:lt(2)") // 小于索引 2
$("p:not(.intro)") // 排除jQuery 事件
jQuery 事件绑定:
// 常见事件
$("#btn").click(function() {
alert("点击了!");
});
// 鼠标事件
$("p").mouseenter(function(){ /* 移入 */ });
$("p").mouseleave(function(){ /* 移出 */ });
$("p").hover(fnIn, fnOut); // 移入移出
$("p").mousedown(fn);
$("p").mouseup(fn);
// 键盘事件
$("#input").keydown(fn);
$("#input").keyup(fn);
$("#input").keypress(fn);
// 表单事件
$("#form").submit(fn);
$("#input").focus(fn);
$("#input").blur(fn);
$("#input").change(fn);
// 事件对象
$("#btn").click(function(event) {
event.preventDefault(); // 阻止默认行为
event.stopPropagation(); // 阻止冒泡
console.log(event.type); // click
});
// on() 统一绑定(推荐)
$("#btn").on("click", function() {
console.log("使用 on()");
});
// 事件委托(动态元素)
$("#list").on("click", "li", function() {
$(this).css("color", "red"); // this 是触发的 li
});
// off() 解绑
$("#btn").off("click");
$("#list").off("click", "li");on() 是 jQuery 3.x 推荐的事件绑定方式,支持事件委托,对动态添加的元素也有效。jQuery 隐藏/显示
jQuery 隐藏/显示:
// 基础
$("#box").hide(); // 隐藏(display:none)
$("#box").show(); // 显示
// 带速度
$("#box").hide(500); // 500ms 渐变
$("#box").show("slow"); // slow/fast/毫秒数
$("#box").show(1000, function() {
console.log("显示完成"); // 回调
});
// toggle:切换
$("#btn").click(function() {
$("#box").toggle(500);
});
// 动画选项
$("#box").hide({
duration: 500,
easing: "swing", // 或 linear
complete: function() { console.log("完成"); }
});jQuery 淡入淡出
jQuery 淡入淡出(透明度动画):
// fadeIn 淡入
$("#box").fadeIn();
$("#box").fadeIn(1000);
$("#box").fadeIn("slow", function() {
console.log("淡入完成");
});
// fadeOut 淡出
$("#box").fadeOut();
$("#box").fadeOut(1000);
// fadeToggle 切换
$("#btn").click(function() {
$("#box").fadeToggle(500);
});
// fadeTo:淡到指定透明度(0-1)
$("#box").fadeTo(1000, 0.3); // 1 秒内变为 30% 不透明
// 应用:图片轮播淡入淡出
$(".slide").first().show();
setInterval(function() {
$(".slide:first").fadeOut(500)
.next().fadeIn(500)
.end().appendTo("#slider");
}, 3000);jQuery 滑动
jQuery 滑动效果(高度动画):
// slideDown 向下展开
$("#panel").slideDown();
$("#panel").slideDown(500);
// slideUp 向上收起
$("#panel").slideUp();
$("#panel").slideUp(500, function() {
console.log("收起完成");
});
// slideToggle 切换
$("#btn").click(function() {
$("#panel").slideToggle(500);
});
// 经典手风琴效果
$(".accordion h3").click(function() {
$(this).next().slideToggle(300);
$(".accordion h3").not(this).next().slideUp(300);
});jQuery 动画
jQuery 自定义动画(animate):
// 基本动画:改变 CSS 属性
$("#box").animate({
left: "300px", // 移动
opacity: 0.5, // 透明度
width: "200px",
height: "200px"
}, 1000);
// 多步动画(链式)
$("#box").animate({ left: "100px" }, 500)
.animate({ top: "100px" }, 500)
.animate({ left: 0, top: 0 }, 500);
// 相对值(+= -=)
$("#box").animate({ left: "+=50px" }, 500);
// 停止动画
$("#stop").click(function() {
$("#box").stop(); // 停止当前动画
$("#box").stop(true); // 清除动画队列
$("#box").stop(true, true); // 立即跳到最终状态
});
// 注意:animate 不能作用于 color(需插件)
$("#box").animate({ backgroundColor: "red" }); // 无效!
$("#box").css("background-color", "red"); // 用 css 直接改animate() 只支持数值型属性(left/top/opacity/width 等),颜色动画需要 jQuery UI 或插件。jQuery 停止动画
停止动画(stop):
// 基本
$("#box").stop();
// 参数说明
// stop(stopAll, goToEnd)
// stopAll: 是否清除动画队列(默认 false)
// goToEnd: 是否立即跳到动画终点(默认 false)
$("#btn1").click(function() {
$("#box").stop(); // 停止当前,继续队列
});
$("#btn2").click(function() {
$("#box").stop(true); // 停止所有
});
$("#btn3").click(function() {
$("#box").stop(true, true); // 停止并跳到终点
});
// 悬停停止:鼠标移入停止,移出继续
$("#box").hover(function() {
$(this).stop();
}, function() {
$(this).animate({ left: "200px" }, 1000);
});
// finish():立即完成所有动画
$("#box").finish();stop() 再动画,否则动画会排队堆积。jQuery Callback
Callback 回调函数:动画/操作完成后执行:
// 基本回调
$("#box").hide(500, function() {
console.log("隐藏完成");
});
// 无回调 vs 有回调
// 无回调:代码立即执行(动画还在进行)
$("#box").hide(1000);
alert("立即弹出");
// 有回调:动画结束后执行
$("#box").hide(1000, function() {
alert("动画完成后弹出");
});
// 回调中的 this 指向被操作元素
$("p").hide(500, function() {
$(this).css("color", "red"); // 每个 p 隐藏后变红
});
// 常见场景:动画后删除
$("#box").fadeOut(500, function() {
$(this).remove(); // 淡出后移除元素
});jQuery 链
jQuery 链(Chaining):一个语句完成多个操作:
// 链式调用
$("#box")
.css("color", "red") // 1. 变色
.slideUp(500) // 2. 收起
.slideDown(500) // 3. 展开
.css("font-size", "20px"); // 4. 改字号
// 原理:大多数 jQuery 方法返回原对象
var box = $("#box");
box.css("color", "red");
box.hide(); // 等价于 box.css(...).hide()
// 需要原始值的方法会中断链(如 text/html/val)
var text = $("#box").text(); // 返回字符串,不能继续链
// end() 回到上一个选择
$("#box").find("span").css("color", "red").end()
.css("border", "1px solid"); // end() 回到 #box
// 链式 + 回调
$("#box").hide(500, function() {
alert("done");
}).show(500);text()/html()/val() 作为 getter 时会返回原始值,中断链条。jQuery 捕获
jQuery 捕获(获取内容):
// 文本内容
var t = $("#box").text(); // 获取纯文本
console.log(t);
// HTML 内容
var h = $("#box").html(); // 获取 HTML
console.log(h);
// 表单值
var v = $("#input").val(); // 获取 input 值
var s = $("#select").val(); // 获取选中值
var c = $("input[name='cb']:checked").val();
// 属性
var src = $("img").attr("src");
var href = $("a").attr("href");
var hasClass = $("#box").hasClass("active");
// CSS
var color = $("#box").css("color");
var width = $("#box").width(); // 内容宽度
var h2 = $("#box").height();
var iw = $("#box").innerWidth(); // +padding
var ow = $("#box").outerWidth(); // +border
// 位置
var pos = $("#box").offset(); // 相对文档
console.log(pos.left, pos.top);
var pos2 = $("#box").position(); // 相对父元素
// 尺寸(整个文档/窗口)
var docW = $(document).width();
var winH = $(window).height();jQuery 设置
jQuery 设置(修改内容):
// 设置文本(会转义 HTML)
$("#box").text("新的文本");
// 设置 HTML(不转义)
$("#box").html("<b>加粗的HTML</b>");
// 设置表单值
$("#input").val("预设值");
$("#select").val("option2");
$("input[name='gender'][value='male']").prop("checked", true);
// 设置属性
$("img").attr("src", "new.jpg");
$("a").attr({ href: "#", title: "提示" });
// 设置 CSS
$("#box").css("color", "red");
$("#box").css({ "font-size": "20px", "background": "#eee" });
// 回调设置
$("#box").text(function(index, oldText) {
return oldText + "(追加)";
});
// prop vs attr(表单状态用 prop)
$("#check").prop("checked", true); // 勾选
$("#check").removeProp("checked");
// attr 用于自定义属性 data-xxx
$("#btn").attr("data-id", "100");checked/disabled/selected 等布尔属性用 prop(),普通属性用 attr()。jQuery 添加元素
jQuery 添加元素:
// 内部追加(子元素末尾)
$("#list").append("<li>追加的项</li>");
// 内部前插(子元素开头)
$("#list").prepend("<li>前插的项</li>");
// 外部后加(兄弟元素之后)
$("#box").after("<div>后面的兄弟</div>");
// 外部前加(兄弟元素之前)
$("#box").before("<div>前面的兄弟</div>");
// 创建元素
var $newItem = $("<li>", {
text: "新项目",
class: "highlight",
"data-id": 5,
click: function() { alert("点击了新项"); }
});
$("#list").append($newItem);
// 移动已有元素
$("#item1").appendTo("#list2"); // 移动(原位置删除)
// 批量添加
$("#list").append(["<li>1</li>", "<li>2</li>", "<li>3</li>"]);jQuery 删除元素
jQuery 删除元素:
// remove():删除元素及其事件
$("#box").remove();
$("#list li").remove(".highlight"); // 按条件删
// empty():清空子元素(保留自身)
$("#box").empty();
// detach():删除但保留事件数据
var $saved = $("#box").detach(); // 可重新放回
$("#parent").append($saved); // 事件仍有效
// unwrap():移除父元素
$("p").unwrap(); // <div><p>内容</p></div> -> <p>内容</p>
// 清理输入
$("#form").trigger("reset"); // 重置表单
$("#form")[0].reset();| 方法 | 区别 | |
|---|---|---|
| remove() | 删除元素 + 事件 | |
| empty() | 清空子元素,留自身 | |
| detach() | 删除但保留事件,可恢复 |
detach(),否则用 remove()。jQuery CSS 类
jQuery CSS 类操作:
// 添加类
$("#box").addClass("active");
$("#box").addClass("active highlight");
// 移除类
$("#box").removeClass("active");
$("#box").removeClass(); // 移除所有类
// 切换类(有则删,无则加)
$("#btn").click(function() {
$("#box").toggleClass("active");
});
// 检查是否含类
if ($("#box").hasClass("active")) {
console.log("有 active 类");
}
// 多个类切换
$("#box").toggleClass("a b c");
// 回调形式
$("#box").toggleClass(function(index, cls) {
return "temp";
});
// 经典应用:标签页切换
$(".tab").click(function() {
$(".tab").removeClass("active");
$(this).addClass("active");
$(".panel").hide().eq($(this).index()).show();
});jQuery css() 方法
css() 方法:
// 获取
var color = $("#box").css("color");
// 设置单个
$("#box").css("background-color", "#f00");
// 设置多个(对象)
$("#box").css({
"color": "#fff",
"background": "#333",
"padding": "10px",
"border-radius": "5px"
});
// 属性名两种写法都行
$("#box").css("background-color"); // 连字符
$("#box").css("backgroundColor"); // 驼峰
// 数值属性(px 可省略)
$("#box").css("width", "200px");
$("#box").css("width", 200); // 等价
// 带 !important
$("#box").css("display", "block !important");
// 应用:动态换主题
$("#themeBtn").click(function() {
$("body").css("background-color", "#222")
.css("color", "#fff");
});jQuery 尺寸
jQuery 尺寸方法:
// 宽度/高度
var w = $("#box").width(); // 内容宽度
var h = $("#box").height(); // 内容高度
// 内尺寸(含 padding)
var iw = $("#box").innerWidth();
var ih = $("#box").innerHeight();
// 外尺寸(含 border,可选含 margin)
var ow = $("#box").outerWidth();
var owm = $("#box").outerWidth(true); // 含 margin
// 设置尺寸
$("#box").width(300);
$("#box").height(150);
$("#box").innerWidth(320);
// 文档与窗口
var docW = $(document).width();
var winW = $(window).width();
var scrollTop = $(window).scrollTop(); // 滚动位置
var scrollLeft = $(window).scrollLeft();
// 滚动到指定位置
$(window).scrollTop(500);
$("html, body").animate({ scrollTop: 0 }, 500); // 平滑回顶
// 元素相对文档位置
var offset = $("#box").offset();
console.log("左:", offset.left, "上:", offset.top);
// 元素相对父级位置
var pos = $("#box").position();jQuery 遍历
jQuery 遍历(Traversing):在 DOM 树中移动/筛选:
// 祖先方向
$("#child").parent(); // 父元素
$("#child").parents(); // 所有祖先
$("#child").parents(".box"); // 匹配的祖先
$("#child").parentsUntil(".wrap"); // 到 .wrap 为止
$("#child").closest(".panel"); // 最近的匹配祖先
// 后代方向
$("#list").children(); // 直接子元素
$("#list").children(".item"); // 筛选
$("#list").find("span"); // 所有后代
// 同胞方向
$("#item2").siblings(); // 所有兄弟
$("#item2").next(); // 下一个
$("#item2").nextAll(); // 后面所有
$("#item2").prev(); // 上一个
$("#item2").prevAll(); // 前面所有
$("#item2").nextUntil(".end"); // 到 .end 为止
// 筛选
$("li").first(); // 第一个
$("li").last(); // 最后一个
$("li").eq(2); // 索引 2
$("li").filter(".active"); // 过滤
$("li").filter(function(i) { // 函数过滤
return $(this).text().length > 3;
});
$("li").not(".disabled"); // 排除
$("li").has("span"); // 含 span 的
$("li").slice(1, 3); // 切片
// 判断
$("#box").is(".visible"); // 是否匹配
$("#box").is(":visible"); // 是否可见
$("#box").is(function() { return $(this).width() > 100; });jQuery 祖先
jQuery 祖先遍历:
// 层级:<html> <body> <div.box> <div.panel> <span#me>
var $me = $("#me");
$me.parent(); // div.panel(直接父)
$me.parents(); // div.panel, div.box, body, html
$me.parents("div"); // div.panel, div.box
$me.parentsUntil("body"); // div.panel, div.box
// closest():从自身向上找最近的匹配
$me.closest("div"); // div.panel(最近的 div)
$me.closest(".box"); // div.box
$me.closest("#me"); // 自身也算
// 区别
// parent() —— 只取直接父
// parents() —— 所有祖先(含 html)
// closest() —— 从自身开始最近的匹配
// parentsUntil() —— 直到某个祖先为止
// 应用:点击行高亮整行
$(".row").click(function() {
$(this).addClass("active")
.siblings().removeClass("active");
});jQuery 后代
jQuery 后代遍历:
// children():只取直接子元素
$("#list").children(); // <li> 们
$("#list").children(".hot"); // 筛选
// find():所有后代(深度搜索)
$("#content").find("p"); // 所有 p
$("#content").find(".highlight"); // 所有匹配
// children vs find
// children 一层,find 全部层级
$("#box").children(); // 直接子
$("#box").find("*"); // 所有后代
// 应用:表格行筛选
$("#search").on("input", function() {
var kw = $(this).val().toLowerCase();
$("#table tbody tr").filter(function() {
return $(this).text().toLowerCase().indexOf(kw) === -1;
}).hide();
$("#table tbody tr").filter(function() {
return $(this).text().toLowerCase().indexOf(kw) >= 0;
}).show();
});jQuery 同胞
jQuery 同胞(Siblings)遍历:
// 兄弟元素:<li>1</li> <li id="two">2</li> <li>3</li>
var $two = $("#two");
$two.siblings(); // li1, li3(不含自身)
$two.next(); // li3
$two.nextAll(); // li3
$two.prev(); // li1
$two.prevAll(); // li1
$two.nextUntil("li:last"); // 到下个特定为止
// 筛选兄弟
$two.siblings(".active");
$two.nextAll(".item");
// 应用:手风琴/标签页(切换兄弟状态)
$(".tab").click(function() {
$(this).addClass("active") // 自己高亮
.siblings().removeClass("active"); // 兄弟取消
var idx = $(this).index();
$(".panel").hide().eq(idx).show();
});jQuery 过滤
jQuery 过滤(Filtering):
// first/last/eq
$("li").first();
$("li").last();
$("li").eq(1);
// filter():选择器或函数
$("li").filter(".active");
$("li").filter(":contains('重要')");
$("li").filter(function(index) {
return $(this).text().length > 5;
});
// not():排除
$("li").not(".disabled");
$("li").not(":first");
// has():包含指定后代的
$("div").has("span"); // 含 span 的 div
// is():判断(返回布尔)
$("li").is(".active"); // 是否有匹配的
$("#box").is(":visible");
$("#box").is(function() {
return $(this).width() > 100;
});
// slice():切片
$("li").slice(0, 3); // 前 3 个
// map():转换
var texts = $("li").map(function() {
return $(this).text();
}).get(); // 转成数组
console.log(texts); // ["a","b","c"]
// each():遍历
$("li").each(function(index, element) {
console.log(index, $(this).text());
});jQuery AJAX 简介
jQuery AJAX 简介:无刷新与服务器交互:
// load():加载 HTML 片段
$("#result").load("page.html #content");
// $.get():GET 请求
$.get("api/data.php", function(data) {
console.log(data);
});
// $.post():POST 请求
$.post("api/save.php",
{ name: "张三", age: 25 },
function(response) {
console.log(response);
}
);
// $.ajax():全能方法
$.ajax({
url: "api/users",
type: "GET", // 或 POST
dataType: "json", // 返回类型
data: { page: 1 },
success: function(data) {
console.log("成功:", data);
},
error: function(xhr, status, error) {
console.log("失败:", error);
},
complete: function() {
console.log("请求结束(无论成败)");
}
});
// 加载提示
$("#btn").click(function() {
$(this).text("加载中...").prop("disabled", true);
$.get("api/data.php", function(data) {
$("#result").html(data);
}).always(function() {
$("#btn").text("加载").prop("disabled", false);
});
});fetch() 或 axios,但理解 $.ajax 的参数(url/type/dataType/success/error)仍是基本功。jQuery load() 方法
load() 方法:从服务器加载数据到元素:
// 基本用法
$("#result").load("content.html");
// 加载指定片段(URL + 空格 + 选择器)
$("#result").load("page.html #main");
// 带参数(POST)
$("#result").load("api/filter.php",
{ category: "books", page: 2 }
);
// 带回调
$("#result").load("content.html", function(response, status, xhr) {
if (status == "success") {
console.log("加载成功,内容长度:", response.length);
} else if (status == "error") {
console.log("加载失败:", xhr.status);
}
});
// 应用:无刷新加载更多
$("#loadMore").click(function() {
var page = $(this).data("page") || 1;
$("#list").load("list.php?page=" + page + " #items", function() {
$(this).data("page", page + 1);
});
});$(选择器).load(url) 一步到位,适合加载 HTML 片段。jQuery get()/post() 方法
get()/post() 方法:
// $.get():GET 请求
$.get("api/user.php", function(data) {
console.log(data);
});
// 带参数
$.get("api/user.php", { id: 5 }, function(data) {
console.log(data);
});
// 指定返回类型
$.get("api/user.json", function(data) {
console.log(data.name); // 自动解析为对象
}, "json");
// $.post():POST 请求
$.post("api/save.php",
{ name: "张三", age: 25 },
function(response) {
console.log(response);
}
);
// 链式:done/fail/always
$.get("api/data.php")
.done(function(data) { console.log("成功", data); })
.fail(function(xhr) { console.log("失败", xhr.status); })
.always(function() { console.log("结束"); });
// 表单序列化提交
$("#form").submit(function(e) {
e.preventDefault();
var data = $(this).serialize(); // a=1&b=2
var data2 = $(this).serializeArray(); // [{name:'a',value:'1'}]
$.post("api/save.php", data, function(res) {
console.log(res);
});
});serialize() 自动收集表单字段,配合 post 提交非常方便。jQuery noConflict() 方法
noConflict() 方法:解决 $ 冲突:
// 场景:其他库也使用了 $(如 Prototype)
// 释放 $ 控制权,改用 jQuery
var jq = jQuery.noConflict();
jq("#box").hide(); // 用 jq 代替 $
jQuery("#box").hide(); // jQuery 仍可用
// $ 现在归其他库使用
// 仍想用 $ 的写法(IIFE 局部作用域)
jQuery.noConflict();
(function($) {
$(function() {
// 在这个函数内 $ 还是 jQuery
$("#box").hide();
});
})(jQuery);
// 用 ready 简写 + noConflict
jQuery(document).ready(function($) {
// ready 回调里 $ 可用
$("#box").hide();
});jQuery 实例
jQuery 实例:综合实战:
<!-- 1. 待办事项 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
.done { text-decoration: line-through; color: #999; }
</style>
</head>
<body>
<input type="text" id="task" placeholder="输入任务">
<button id="add">添加</button>
<ul id="list"></ul>
<script>
$(function() {
// 添加任务
$("#add").click(function() {
var text = $("#task").val().trim();
if (!text) return;
$("#list").append(
"<li><input type='checkbox' class='done'> " +
"<span>" + $("<span>").text(text).html() + "</span> " +
"<button class='del'>删除</button></li>"
);
$("#task").val("");
});
// 回车添加
$("#task").keypress(function(e) {
if (e.which == 13) $("#add").click();
});
// 完成/取消(事件委托)
$("#list").on("change", "input.done", function() {
$(this).next().toggleClass("done");
});
// 删除
$("#list").on("click", "button.del", function() {
$(this).parent().fadeOut(300, function() {
$(this).remove();
});
});
});
</script>
</body>
</html>jQuery 事件方法
jQuery 事件方法速查:
| 事件 | 方法 | 触发时机 |
|---|---|---|
| 点击 | click() | 鼠标点击 |
| 双击 | dblclick() | 双击 |
| 移入 | mouseenter() | 进入元素 |
| 移出 | mouseleave() | 离开元素 |
| 悬停 | hover(in,out) | 移入+移出 |
| 按下 | mousedown() | 按下鼠标 |
| 松开 | mouseup() | 松开鼠标 |
| 聚焦 | focus() | 获得焦点 |
| 失焦 | blur() | 失去焦点 |
| 输入 | keydown()/keyup() | 按键 |
| 改变 | change() | 值变化 |
| 提交 | submit() | 表单提交 |
| 滚动 | scroll() | 滚动 |
| 调整 | resize() | 窗口调整 |
| 加载 | load() | 元素加载 |
// 统一绑定
$("#btn").on("click", fn);
$("#btn").on({
mouseenter: fn1,
mouseleave: fn2,
click: fn3
});
// 一次性
$("#btn").one("click", function() {
console.log("只执行一次");
});
// 触发事件
$("#btn").trigger("click");
$("#btn").click(); // 简写触发
$("#form").trigger("submit");jQuery 效果方法
jQuery 效果方法速查:
| 方法 | 效果 | 参数 |
|---|---|---|
| hide() | 隐藏 | speed,easing,callback |
| show() | 显示 | speed,easing,callback |
| toggle() | 切换显隐 | speed,easing,callback |
| fadeIn() | 淡入 | speed,callback |
| fadeOut() | 淡出 | speed,callback |
| fadeToggle() | 切换淡入淡出 | speed,callback |
| fadeTo() | 淡到指定透明度 | speed,opacity,callback |
| slideDown() | 向下展开 | speed,callback |
| slideUp() | 向上收起 | speed,callback |
| slideToggle() | 切换滑动 | speed,callback |
| animate() | 自定义动画 | params,speed,easing,callback |
| stop() | 停止动画 | stopAll,goToEnd |
| delay() | 延迟执行 | ms |
| finish() | 完成所有动画 | - |
// 组合使用
$("#box").delay(500).slideDown(500).delay(500).slideUp(500);
// speed 取值
$("#box").hide("slow"); // 600ms
$("#box").hide("fast"); // 200ms
$("#box").hide(1000); // 1000ms
// easing
$("#box").animate({left: "100px"}, {duration: 500, easing: "linear"});jQuery HTML / CSS 方法
jQuery HTML/CSS 方法速查:
| 类别 | 方法 | 说明 |
|---|---|---|
| 内容 | text() | 获取/设置纯文本 |
| 内容 | html() | 获取/设置 HTML |
| 内容 | val() | 获取/设置表单值 |
| DOM | append()/prepend() | 内部追加/前插 |
| DOM | after()/before() | 外部后加/前加 |
| DOM | remove()/empty() | 删除/清空 |
| CSS | addClass()/removeClass() | 添加/移除类 |
| CSS | toggleClass() | 切换类 |
| CSS | css() | 获取/设置样式 |
| 尺寸 | width()/height() | 宽高 |
| 尺寸 | innerWidth()/outerWidth() | 含 padding/border |
| 位置 | offset()/position() | 位置 |
| 滚动 | scrollTop()/scrollLeft() | 滚动位置 |
// 综合示例
$("#box")
.text("新文本")
.addClass("highlight")
.css("color", "red")
.width(300)
.slideDown(500);jQuery 遍历方法
jQuery 遍历方法速查:
| 方向 | 方法 | 说明 |
|---|---|---|
| 祖先 | parent() | 直接父元素 |
| 祖先 | parents() | 所有祖先 |
| 祖先 | parentsUntil() | 直到某祖先 |
| 祖先 | closest() | 最近的匹配祖先 |
| 后代 | children() | 直接子元素 |
| 后代 | find() | 所有后代 |
| 同胞 | siblings() | 所有兄弟 |
| 同胞 | next()/nextAll() | 后续兄弟 |
| 同胞 | prev()/prevAll() | 前置兄弟 |
| 过滤 | first()/last() | 首/尾 |
| 过滤 | eq() | 指定索引 |
| 过滤 | filter()/not() | 过滤/排除 |
| 过滤 | has() | 含后代的 |
| 过滤 | is() | 判断 |
| 过滤 | each() | 遍历 |
| 过滤 | map() | 转换 |
// 遍历 + 过滤组合
$("ul li").filter(".active").each(function(i) {
console.log(i, $(this).text());
});jQuery AJAX 方法
jQuery AJAX 方法速查:
| 方法 | 说明 |
|---|---|
| $.ajax() | 全能 AJAX 方法 |
| $.get() | GET 请求 |
| $.post() | POST 请求 |
| $.getJSON() | 获取 JSON |
| $.getScript() | 动态加载 JS |
| load() | 加载 HTML 到元素 |
| serialize() | 序列化表单 |
| serializeArray() | 序列化为数组 |
| ajaxSetup() | 设置全局默认 |
| ajaxStart()/ajaxStop() | 全局事件 |
// getJSON
$.getJSON("api/data.json", function(data) {
console.log(data);
});
// 全局加载动画
$(document).ajaxStart(function() {
$("#loading").show();
}).ajaxStop(function() {
$("#loading").hide();
});jQuery 杂项方法
jQuery 杂项方法:
// 工具函数
$.trim(" hello "); // "hello"(去空格)
$.isArray([1,2]); // true
$.isFunction(fn); // true
$.isNumeric("42"); // true
$.isEmptyObject({}); // true
$.extend({a:1}, {b:2}); // 合并对象 {a:1,b:2}
$.each([1,2,3], function(i, v) { console.log(i, v); });
$.map([1,2,3], function(v) { return v * 2; }); // [2,4,6]
$.inArray(2, [1,2,3]); // 1(索引)
$.now(); // 时间戳
$.parseJSON('{"a":1}'); // 解析 JSON(已废弃,用 JSON.parse)
// 判断对象
var $el = $("#box");
$el.length; // 选择器命中数量
$el.is(":visible");
$el.index(); // 在兄弟中的索引
$el.index("#list li"); // 在指定集合中的索引
$("#box").data("key", "value"); // 存储数据
$("#box").data("key"); // 读取数据
$("#box").removeData("key");$.each 遍历数组/对象,$(el).each 遍历 jQuery 集合。jQuery 属性
jQuery 属性方法:
// attr():获取/设置属性
$("img").attr("src");
$("img").attr("src", "new.jpg");
$("a").attr({ href: "#", target: "_blank" });
// prop():属性状态
$("#check").prop("checked"); // true/false
$("#btn").prop("disabled", true); // 禁用
$("input").prop("required", true);
// attr vs prop 总结
// attr: 自定义属性、HTML 初始属性
// prop: checked/disabled/selected 等布尔状态
// removeAttr / removeProp
$("a").removeAttr("target");
$("#btn").removeProp("disabled");
// data():HTML5 data-* 属性
// <div id="card" data-id="5" data-name="商品A">
$("#card").data("id"); // 5(自动转数字)
$("#card").data("name"); // "商品A"
$("#card").data("price", 99); // 设置
// val():表单值
$("#input").val();
$("#input").val("新值");
$("#select").val("option3");data() 读取 HTML5 data-* 属性时自动转换类型,适合存业务数据。jQuery Validate
jQuery Validate:表单验证插件:
<!-- 引入插件 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-validate/1.19.5/jquery.validate.min.js"></script>// 基本验证
$("#myForm").validate({
rules: {
name: { required: true, minlength: 2 },
email: { required: true, email: true },
age: { required: true, number: true, min: 18 },
password: { required: true, minlength: 6 },
confirm: { equalTo: "#password" }
},
messages: {
name: { required: "请输入姓名", minlength: "至少2个字符" },
email: { required: "请输入邮箱", email: "邮箱格式错误" },
age: { required: "请输入年龄", min: "必须年满18岁" },
password: { required: "请输入密码", minlength: "至少6位" },
confirm: { equalTo: "两次密码不一致" }
},
submitHandler: function(form) {
// 验证通过后提交
alert("验证通过,提交表单");
form.submit();
}
});
// 自定义规则
$.validator.addMethod("phoneCN", function(value, el) {
return /^1[3-9]\d{9}$/.test(value);
}, "请输入正确的手机号");
$("#myForm").validate({
rules: { phone: { required: true, phoneCN: true } }
});jQuery Cookie
jQuery Cookie 插件:
<!-- 引入插件 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>// 写入 Cookie
$.cookie("username", "zhangsan");
$.cookie("theme", "dark", { expires: 7 }); // 7 天后过期
$.cookie("lang", "zh", { expires: 30, path: "/" });
// 读取
var name = $.cookie("username");
console.log(name); // zhangsan
// 删除
$.removeCookie("username");
$.removeCookie("theme", { path: "/" }); // 需与写入的 path 一致
// 应用:记住主题偏好
$("#themeBtn").click(function() {
$("body").toggleClass("dark");
var isDark = $("body").hasClass("dark");
$.cookie("theme", isDark ? "dark" : "light", { expires: 30 });
});
// 页面加载时读取
$(function() {
if ($.cookie("theme") == "dark") {
$("body").addClass("dark");
}
});jQuery Accordion
jQuery Accordion 手风琴效果:
<!-- 结构 -->
<div class="accordion">
<h3>面板一</h3>
<div><p>内容一</p></div>
<h3>面板二</h3>
<div><p>内容二</p></div>
<h3>面板三</h3>
<div><p>内容三</p></div>
</div>// 用 jQuery UI 的 accordion 组件
$(".accordion").accordion({
collapsible: true, // 允许全部收起
heightStyle: "content", // 高度自适应
animate: 300 // 动画时长
});
// 或手写实现(更轻量)
$(".accordion h3").click(function() {
var $panel = $(this).next();
if ($panel.is(":visible")) {
$panel.slideUp(300);
} else {
$(".accordion .content").slideUp(300);
$panel.slideDown(300);
}
});jQuery Autocomplete
jQuery Autocomplete 自动补全:
<!-- 引入 jQuery UI -->
<link href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css" rel="stylesheet">
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
<input id="tags" placeholder="输入关键字">// 本地数据
var cities = ["北京", "上海", "广州", "深圳", "杭州", "南京", "成都", "武汉"];
$("#tags").autocomplete({
source: cities,
minLength: 1 // 输入 1 个字符开始提示
});
// 远程数据(AJAX)
$("#tags").autocomplete({
source: function(request, response) {
$.getJSON("api/search.php", {
term: request.term // 用户输入
}, response);
},
select: function(event, ui) {
// 选中项回调
console.log("选择了:", ui.item.value);
return true;
}
});
// 自定义显示
$("#tags").autocomplete({
source: [
{ label: "JavaScript 教程", value: "js" },
{ label: "Java 教程", value: "java" },
{ label: "jQuery 教程", value: "jq" }
],
minLength: 0
});jQuery Growl
jQuery Growl 通知消息效果:
<!-- 引入插件 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css" rel="stylesheet">// 简单的提示消息(自实现)
function growl(message, type) {
var $msg = $("<div>", {
class: "growl " + (type || "info"),
text: message
});
$("body").append($msg);
$msg.css({
position: "fixed",
top: "20px",
right: "20px",
padding: "12px 20px",
background: type == "error" ? "#e74c3c"
: type == "success" ? "#2ecc71" : "#3498db",
color: "#fff",
"border-radius": "4px",
"z-index": 9999
}).hide().slideDown(300).delay(2500).slideUp(300, function() {
$(this).remove();
});
}
// 使用
growl("保存成功!", "success");
growl("网络错误", "error");
growl("欢迎回来", "info");
// 自动定位多个消息
function growlStacked(message, type) {
var $msg = $("<div>", { class: "growl", text: message });
var top = 20;
$(".growl").each(function() {
top += $(this).outerHeight() + 10;
});
$msg.css({ position: "fixed", top: top, right: "20px" })
.hide().fadeIn(300).delay(2500).fadeOut(300, function() {
$(this).remove();
});
$("body").append($msg);
}jQuery 密码验证
jQuery 密码验证:
// 实时密码强度检测
$("#password").on("input", function() {
var pwd = $(this).val();
var score = 0;
if (pwd.length >= 8) score++;
if (/[A-Z]/.test(pwd)) score++; // 大写
if (/[a-z]/.test(pwd)) score++; // 小写
if (/[0-9]/.test(pwd)) score++; // 数字
if (/[^A-Za-z0-9]/.test(pwd)) score++; // 符号
var levels = ["极弱", "弱", "一般", "良好", "强", "极强"];
var colors = ["#e74c3c", "#e74c3c", "#f39c12",
"#2ecc71", "#27ae60", "#16a085"];
var idx = Math.min(score, levels.length - 1);
$("#strength").text(levels[idx])
.css("color", colors[idx]);
});
// 确认密码
$("#confirm").on("input", function() {
var ok = $(this).val() == $("#password").val();
$("#confirmTip").text(ok ? "✓ 一致" : "✗ 两次密码不一致")
.css("color", ok ? "green" : "red");
});
// 表单提交校验
$("#regForm").submit(function(e) {
var pwd = $("#password").val();
var confirm = $("#confirm").val();
if (pwd.length < 8) {
e.preventDefault();
alert("密码至少 8 位");
} else if (pwd != confirm) {
e.preventDefault();
alert("两次密码不一致");
}
});jQuery Prettydate
jQuery Prettydate:人性化时间显示:
<!-- 引入插件 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery-timeago/1.6.7/jquery.timeago.min.js"></script>// 原理:把时间戳显示为"xx 前"
// 原生实现
function prettyDate(dateStr) {
var diff = (Date.now() - new Date(dateStr)) / 1000;
var units = [
{ name: "年", sec: 31536000 },
{ name: "月", sec: 2592000 },
{ name: "天", sec: 86400 },
{ name: "小时", sec: 3600 },
{ name: "分钟", sec: 60 }
];
for (var i = 0; i < units.length; i++) {
var n = Math.floor(diff / units[i].sec);
if (n >= 1) return n + " " + units[i].name + "前";
}
return "刚刚";
}
// 使用
$("time.pretty").each(function() {
var $t = $(this);
var date = $t.attr("datetime");
$t.text(prettyDate(date));
// 每分钟更新
setInterval(function() {
$t.text(prettyDate($t.attr("datetime")));
}, 60000);
});
// jQuery Timeago 插件用法
$("time.timeago").timeago();jQuery Tooltip
jQuery Tooltip 提示框:
<!-- 引入 jQuery UI -->
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>jQuery Treeview
jQuery Treeview 树形菜单:
<!-- 结构 -->
<ul id="tree">
<li>前端
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</li>
<li>后端
<ul>
<li>Python</li>
<li>Java</li>
<li>PHP</li>
</ul>
</li>
<li>数据库</li>
</ul>// 手写树形展开/收起
$("#tree li:has(ul)").addClass("has-children").prepend("<span class='arrow'>▸ </span>");
$("#tree li:has(ul) > ul").hide();
$("#tree").on("click", ".arrow", function() {
var $li = $(this).parent();
$li.children("ul").slideToggle(200);
$(this).toggleClass("open");
});
// 递归加载远程数据
function buildTree(container, nodes) {
var $ul = $("<ul>");
$.each(nodes, function(i, node) {
var $li = $("<li>").text(node.name).appendTo($ul);
if (node.children && node.children.length) {
$li.append(buildTree(null, node.children));
$li.children("ul").hide();
}
});
return container ? container.append($ul) : $ul;
}
var data = [
{ name: "菜单一", children: [
{ name: "子项1-1" },
{ name: "子项1-2" }
]},
{ name: "菜单二" }
];
buildTree($("#menu"), data);
// 手风琴模式(同级互斥)
$("#tree").on("click", "li", function() {
$(this).children("ul").slideToggle(200);
$(this).siblings("li").children("ul").slideUp(200);
});jQuery API 手册
jQuery API 手册:核心速查:
| 分类 | 核心 API |
|---|---|
| 核心 | $(), jQuery()、.each()、.length、.index() |
| 选择器 | #id、.class、:eq()、:first、[attr] |
| DOM | .text() .html() .val() .attr() .prop() |
| DOM 操作 | .append() .prepend() .after() .before() .remove() .empty() |
| CSS | .css() .addClass() .removeClass() .toggleClass() .hasClass() |
| 尺寸 | .width() .height() .innerWidth() .outerWidth() |
| 事件 | .on() .off() .one() .trigger() .click() .hover() .submit() |
| 效果 | .show() .hide() .toggle() .fadeIn() .fadeOut() .slideUp() .slideDown() .animate() .stop() |
| 遍历 | .parent() .parents() .closest() .children() .find() .siblings() .next() .prev() .filter() .eq() .first() .last() .is() |
| AJAX | $.ajax() $.get() $.post() .load() .serialize() |
| 工具 | $.each() $.map() $.extend() $.trim() $.isArray() $.now() |
| 数据 | .data() .removeData() |
// 官方文档
// https://api.jquery.com/
// 速查技巧:jQuery 对象方法链
$("#box")
.css("color", "red") // 样式
.slideDown(300) // 动画
.on("click", handler) // 事件
.data("id", 42); // 数据