jQuery 练习题(10 题)
这一页给 10 道 jQuery 练习题,覆盖引入与 ready、选择器、事件、文本/HTML、CSS 类、DOM 增删改、动画、AJAX、遍历、实战这些最核心的知识点。每题都有题目描述、提示、可折叠的参考答案。
使用建议:先自己动手写,卡住了再看提示,实在写不出再对照答案。jQuery 虽然 React/Vue 时代用得少了,但它是「操作 DOM」的最直白范式,理解了它,前端的基础概念就稳了。
基础(5 题):引入 / 选择器 / 事件 / 文本 / CSS
第 1 题:引入 jQuery 与 $(document).ready
题目:用 CDN 方式引入 jQuery 3.x,写一段在 DOM 就绪后执行的代码,打印 jQuery 版本号,并把某个元素文本改成 hello jQuery。同时给出 $(document).ready(fn) 的简写形式。
提示:$.fn.jquery 可读版本;ready 比 window.onload 早触发(后者要等图片等资源);简写直接 $(fn)。脚本最好放 body 结束前,或用 defer。
参考答案
<!-- 通过 CDN 引入 jQuery(放 body 结束前,不阻塞首屏) -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
// 等待 DOM 树构建完再执行,避免脚本拿不到元素
$(document).ready(function () {
console.log('DOM 就绪');
console.log('jQuery 版本:', $.fn.jquery);
});
// 简写形式(推荐):等价于 $(document).ready(...)
$(function () {
$('#title').text('hello jQuery');
});
</script>
<!-- 知识点:
- ready 触发时机:DOM 解析完即可,不等待图片/CSS/iframe
- window.onload 是等所有资源加载完,晚得多
- 现代写法:$(fn) 或 $(() => { ... }) -->第 2 题:选择器
题目:用 jQuery 选择器实现以下需求:(a) 选中 id 为 logo 的元素;(b) 选中所有 class 含 item 的元素;(c) 选中 ul.nav 下所有 li(任意层级)和直接子 li;(d) 同时选 h2 和 h3;(e) 选第一个和索引为 2 的 li;(f) 选当前可见的元素和被勾选的复选框。
提示:基础选择器 $('#id')、$('.cls')、$('tag');后代空格、子代 >、多选逗号;过滤伪类 :first、:eq(n)、:odd、:visible、:checked。坑:选择器永远返回 jQuery 对象,即使没匹配也不会是 null——要用 .length 判断。
参考答案
$(function () {
// 基础选择器(返回的是 jQuery 对象,不是原生 DOM)
$('#logo') // id 选择器:页面里唯一
$('.item') // class 选择器:可多个
$('div') // 标签选择器
$('*') // 全选(慎用,慢)
// 组合
$('ul.nav li') // 后代:nav 下的所有 li(任意层级)
$('ul.nav > li') // 子代:仅直接子元素
$('h2, h3') // 多选:逗号分隔
// 位置与可见性过滤
$('li:first') // 第一个
$('li:eq(2)') // 索引为 2 的(第 3 个,从 0 计)
$('li:odd') // 索引为奇数(注意是从 0 计,视觉上是偶数行)
$('li:visible') // 当前可见的
$('input:checked') // 选中的复选框/单选
});第 3 题:事件处理
题目:写一个按钮点击事件,在回调里拿到事件对象和触发元素;再用 .hover() 实现鼠标进入加类、离开移除类;再用事件委托给一个 ul 里的 li 绑点击(li 是动态生成的);最后实现「只触发一次」的点击。
提示:.on('click', fn) 是推荐写法;this 在回调里是原生 DOM,要包 $(this) 才能用 jQuery 方法;事件委托用 .on(event, selector, fn) 三参形式,父元素监听子元素冒泡上来的事件——这是处理动态元素的标准做法。
参考答案
$(function () {
// 基本点击
$('#btn').on('click', function (e) {
console.log('点了', this); // this 是触发事件的原生 DOM
console.log('事件对象', e.type);
});
// hover 实际是 mouseenter + mouseleave 的语法糖
$('#box').hover(
function () { $(this).addClass('hot'); }, // 进入
function () { $(this).removeClass('hot'); } // 离开
);
// 事件委托:子元素是动态生成的,父元素上委托
$('#list').on('click', 'li', function (e) {
console.log('点到的是 li,内容:', $(this).text());
});
// 只触发一次
$('#once').one('click', function () {
alert('只触发这一次');
});
// 取消绑定
// $('#btn').off('click');
});第 4 题:操作文本与 HTML
题目:分别读取和设置某元素的纯文本、HTML 内容、表单值。再用「传函数」的方式,把某个数字元素的文本自增 1。
提示:.text() 纯文本(标签会被转义),.html() 含 HTML(会解析),.val() 表单值;三者都支持「传函数」形式 fn(i, oldValue)。安全警告:用户输入直接 .html() 会触发 XSS——必须先转义或用 .text()。
参考答案
$(function () {
// 读取
$('#title').text(); // 纯文本(不含 HTML 标签)
$('#box').html(); // 含 HTML 标签
$('#name').val(); // 表单值(input/textarea/select)
// 写入
$('#title').text('新标题'); // 转义 HTML,原样显示
$('#box').html('<strong>加粗</strong>'); // 当作 HTML 解析
$('#name').val('张三');
// 传函数:基于旧值计算新值(对应元素的索引、旧值)
$('#count').text(function (i, old) {
return Number(old) + 1; // 自增
});
// 注意:.text() 读到的标签会被转义显示,
// .html() 才会按 HTML 渲染。安全警告:用户输入直接 .html() 会 XSS。
});第 5 题:操作 CSS 类与样式
题目:给元素加、删、切换 active 类,判断是否含此类;再用对象形式一次性设置 color/background/font-size 三条样式;最后读取元素的计算后 font-size。
提示:.addClass/.removeClass/.toggleClass/.hasClass 四件套;多条样式用 .css({ key: val, ... }),带连字符的 key 要加引号;原则:批量改样式优先用 class(性能好、易维护),.css 用于动态值。
参考答案
$(function () {
// 类操作(批量改样式优先用 class,而不是逐条 .css)
$('#box').addClass('active'); // 添加
$('#box').removeClass('active'); // 移除
$('#box').toggleClass('active'); // 切换
$('#box').hasClass('active'); // 判断:返回 boolean
// 多类空格分隔
$('#box').addClass('a b c');
// 行内样式
$('#box').css('color', 'red'); // 单个
$('#box').css({ // 多个(对象)
color: '#fff',
background: '#000',
'font-size': '14px'
});
$('#box').css('font-size'); // 读取计算后的样式值
});进阶(5 题):DOM / 动画 / AJAX / 遍历 / 实战
第 6 题:DOM 增删改
题目:创建一个新的 <li> 追加到列表末尾;把一个 <hr> 插到某元素后面;读取并设置图片的 src/alt;移除一个属性;最后清空一个元素的所有子节点但保留自身。
提示:$('HTML 字符串') 创建元素;.appendTo/.prepend/.after/.before 四个插入位置;.attr 操作任意属性,.prop 操作布尔属性(checked/disabled 等,读实时状态而非 HTML 初始值);.remove() 连自身删,.empty() 只删后代。
参考答案
$(function () {
// 增
$('<li>新项</li>').appendTo('#list'); // 创建后追加到末尾
$('#list').prepend('<li>置顶</li>'); // 插到开头
$('#list').after('<hr>'); // 作为兄弟插到自己后面
$('#list').before('<h3>标题</h3>'); // 作为兄弟插到自己前面
// 改属性
$('#pic').attr('src', 'cat.jpg'); // 设置
$('#pic').attr('alt'); // 读取
$('#pic').removeAttr('alt'); // 删除属性
// prop vs attr:布尔属性(checked/disabled)用 prop
$('#cb').prop('checked', true);
$('#cb').prop('checked'); // true(读实时状态)
$('#cb').attr('checked'); // 'checked'(读初始 HTML)
// 删
$('#item').remove(); // 连自身一起从 DOM 删掉
$('#list').empty(); // 只清空后代,保留自身
});第 7 题:显示隐藏动画
题目:实现四个按钮:(a) 显隐切换;(b) 淡出后再淡入;(c) 滑动展开/收起;(d) 用 .animate() 把宽度增加 50px 同时透明度变 0.5。每段动画都要带回调。
提示:.show/.hide/.toggle 同时动宽高+透明度;.fadeIn/.fadeOut/.fadeToggle 只动透明度;.slideDown/.slideUp/.slideToggle 只动高度;动画时长第一个参数(毫秒或 'slow'/'fast'),第二个是回调。注意:jQuery 内置不支持颜色动画,需要 jQuery UI 或插件。
参考答案
$(function () {
$('#btnShow').on('click', function () {
$('#box').show(); // 立即显示
$('#box').show(400); // 400ms 过渡(宽高+透明度)
});
$('#btnHide').on('click', function () {
$('#box').hide(400);
});
$('#btnToggle').on('click', function () {
$('#box').toggle(400); // 切换显隐
});
// 淡入淡出(只动透明度)
$('#fadeBtn').on('click', function () {
$('#box').fadeOut(300, function () {
// 动画完成的回调,this 是 DOM
$(this).fadeIn(300);
});
});
// 滑动(只动高度)
$('#slideBtn').on('click', function () {
$('#box').slideToggle(300);
});
// 自定义动画(注意:颜色动画要插件)
$('#box').animate({ width: '+=50', opacity: 0.5 }, 400);
});第 8 题:AJAX 请求
题目:分别用 (a) $.get 带 page 参数请求 JSON;(b) $.post 提交登录表单;(c) $.ajax 做 PUT 请求,用 .done/.fail/.always 处理三种结果,并设置 5 秒超时。
提示:简写 $.get/post(url, data, successCb, dataType);$.ajax 最全;dataType: 'json' 让 jQuery 自动解析;跨域需后端配 CORS。坑:旧版的 .success/.error 已废弃,务必用 .done/.fail 或 Promise 风格。
参考答案
$(function () {
// 简写:GET
$.get('/api/users', { page: 1 }, function (data) {
console.log('用户列表', data);
}, 'json');
// 简写:POST
$.post('/api/login', { user: 'a', pwd: 'b' }, function (resp) {
console.log('登录结果', resp);
}, 'json');
// 通用 $.ajax(功能最全,支持 Promise)
$.ajax({
url: '/api/user/12',
method: 'PUT',
data: { name: '张三', age: 28 },
dataType: 'json',
timeout: 5000
})
.done(function (data) { console.log('成功', data); })
.fail(function (xhr, status, err) { console.log('失败', err); })
.always(function () { console.log('不管成败都执行'); });
});
<!-- 知识点:
- dataType 让 jQuery 自动解析响应(json/html/text)
- 跨域需后端配 CORS,或服务端用 JSONP(jq 已支持)
- jq 3+ 推荐 .done/.fail,旧版 .success 已废弃 -->第 9 题:遍历
题目:遍历所有 li 打印索引和文本;从一个元素出发,分别用 .find/.children/.parent/.parents/.closest/.siblings/.next/.prev;最后写一条链式调用,给第一个 li 加 hl 类并给它的所有兄弟移除 hl。
提示:.each(fn) 里 this 是原生 DOM;.find 找后代,.children 只找直接子;.parents 向上找所有祖先,.closest 向上找第一个匹配(最常用);.filter/.not/.eq 在当前集合里筛选。链式调用能工作的原因:每步都返回新的 jQuery 对象。
参考答案
$(function () {
// 遍历集合(this 是原生 DOM)
$('li').each(function (i, el) {
console.log(i, $(this).text());
});
// 查子代 / 后代
$('#box').find('.tag'); // 所有匹配 .tag 的后代
$('#box').children(); // 仅直接子元素
$('#box').children('.item'); // 直接子元素里再过滤
// 找父级 / 兄弟
$('li').parent(); // 直接父
$('li').parents('.list'); // 向上找所有祖先中匹配 .list 的
$('li').closest('.item'); // 向上最近的匹配(常用)
$('li').siblings(); // 兄弟(不含自己)
$('li').next(); // 下一个兄弟
$('li').prev(); // 上一个
$('li').nextAll(); // 后面所有兄弟
// 链式调用:每步都返回 jQuery 对象
$('li').first().addClass('hl').siblings().removeClass('hl');
// 过滤
$('li').filter('.active'); // 保留匹配的
$('li').not('.active'); // 排除匹配的
$('li').eq(2); // 取索引 2 的
});第 10 题:实战:待办清单
题目:实现一个完整的 todo list:输入框 + 添加按钮(回车也能添加);点击「完成」按钮给该项加删除线样式(再次点击取消);点击「删」按钮先淡出再移除。要求用事件委托处理动态生成的 li。
提示:这是 jQuery 最经典的应用场景。关键点:(1) 用字符串拼接构造 <li> 后 .append;(2) $('#list').on('click', '.done', fn) 三参形式做事件委托;(3) $(this).closest('.todo') 从按钮向上找到 li;(4) .fadeOut(cb) 在回调里 .remove(),注意回调里 this 已变,要在外层缓存 $li。
参考答案
<!-- HTML -->
<input id="todo-input" placeholder="输入任务,回车添加">
<button id="add-btn">添加</button>
<ul id="todo-list"></ul>
<style>
.completed .text { text-decoration: line-through; color: #aaa; }
</style>
<script>
$(function () {
// 添加(支持点击和回车两种方式)
function addTodo() {
var txt = $('#todo-input').val().trim();
if (!txt) return;
// 动态拼接 li,带"完成"和"删"按钮
var $li = $(
'<li class="todo">' +
' <span class="text">' + txt + '</span>' +
' <button class="done">完成</button>' +
' <button class="del">删</button>' +
'</li>'
);
$('#todo-list').append($li);
$('#todo-input').val('').focus();
}
$('#add-btn').on('click', addTodo);
$('#todo-input').on('keydown', function (e) {
if (e.key === 'Enter') addTodo();
});
// 完成切换:用事件委托,因为 li 是动态生成的
$('#todo-list').on('click', '.done', function () {
$(this).closest('.todo').toggleClass('completed');
});
// 删除:淡出后再 remove
$('#todo-list').on('click', '.del', function () {
var $li = $(this).closest('.todo');
$li.fadeOut(200, function () { $li.remove(); });
});
});
</script>
<!-- 知识点:
- 动态生成的元素,直接 $('#todo-list .done').on(...) 绑不上
- 用事件委托:父元素监听,第二个参数过滤目标
- closest(selector) 是从触发点向上找最近的祖先匹配,极常用 -->练习建议
jQuery 的核心就一句话:「选元素,然后做事」。掌握选择器(基础+过滤)、事件(尤其事件委托)、DOM 操作(增删改)、链式调用,90% 的需求都能搞定。动画和 AJAX 是锦上添花。
做完这 10 题,试着把第 10 题扩展一下:加「编辑」按钮(双击 li 进入编辑态)、用 localStorage 持久化、加「全选/反选」——把这些组合起来,就是一个完整的前端小项目了。
← 上一篇 jQuery 插件
返回 jQuery 教程目录