首页 / 资讯中心 / 文章详情

jQuery初识实战:从选择器到动画的完整案例练习

jQuery初识实战:从选择器到动画的完整案例练习 ★ FEATURED ARTICLE
1. 从零上手jQuery为什么今天还要练这个“老古董”打开任何一个前端技术社区搜索“jQuery”你大概率会看到两种截然对立的论调。一种说“都什么年代了还学jQueryVue和React不香吗”另一种说“连jQuery都不会算什么前端”。这两种说法其实都有点极端。我自己的判断是jQuery在今天依然有它不可替代的练习价值尤其是对于刚接触DOM操作、事件绑定、动画效果这些基础概念的初学者来说它是一块非常好的“磨刀石”。为什么这么说因为jQuery把浏览器原生DOM操作中大量繁琐、重复、兼容性差的代码封装成了一套极其简洁的链式调用接口。你写$(.box).addClass(active)就能给所有带box类的元素加上active类而用原生JavaScript你得写document.querySelectorAll(.box)然后遍历、逐个classList.add。这种“一句话干一件事”的爽快感能让初学者把注意力集中在“我要实现什么效果”上而不是被浏览器兼容性和冗长的API签名绊住脚。这篇内容就是围绕“jQuery初识”这个主题通过一系列由浅入深的案例练习把jQuery最核心的几个能力——选择器、DOM操作、事件处理、动画效果、链式调用——串起来讲透。不管你是刚学完HTML和CSS、准备踏入JavaScript世界的新手还是已经用过Vue但想回头补一补“底层手感”的开发者这些案例都能帮你建立起对jQuery的直观认知。我会把每个案例的完整代码、实现思路、容易踩的坑以及“为什么这样写而不是那样写”都掰开揉碎讲清楚。你跟着敲一遍基本就能独立用jQuery做常见的页面交互效果了。2. 动手前的环境准备与jQuery引入方式选择2.1 三种引入方式的实际取舍在开始写第一个案例之前得先把jQuery“请”进你的页面。常见的方式有三种每种都有它适合的场景不是随便选一个就行。第一种是通过CDN引入。在HTML的head或body末尾加一行script srchttps://cdn.example.com/jquery-3.7.1.min.js/script就行。这种方式的好处是零配置、不占本地空间适合快速做demo或者练习。但要注意CDN地址得选可靠的否则加载失败你的页面就全瘫了。练习阶段我建议用这种方式省事。第二种是把jQuery文件下载到本地放在项目目录里然后用相对路径引入。比如script src./lib/jquery-3.7.1.min.js/script。这种方式适合正式项目不依赖外部网络加载速度可控。下载的时候注意选压缩版文件名带.min的体积小加载快。第三种是通过包管理器安装比如npm。这种方式适合用Webpack、Vite这类构建工具的项目。但对于“初识jQuery”的练习来说有点杀鸡用牛刀了前期不建议折腾。提示不管你用哪种方式引入jQuery的script标签一定要放在你自己写的脚本之前否则$符号还没定义你的代码就会报$ is not defined。这个错误新手几乎百分百会遇到一次。2.2 版本选择与一个容易忽略的细节jQuery目前主流是3.x版本它和2.x、1.x在API上大部分兼容但3.x移除了一些废弃方法也改了一些行为。练习阶段直接用最新的3.7.x就行。有一个细节很多人不注意jQuery有“完整版”和“slim版”之分。slim版去掉了Ajax和动画效果模块体积更小。如果你确定不需要用$.ajax和.animate()这些可以用slim版。但初学阶段我建议用完整版免得写到一半发现某个方法不存在还得回头换。另外引入之后可以写一行console.log($.fn.jquery)来确认版本号确保加载成功。这行代码在调试时很有用能快速判断是jQuery没加载还是你的代码写错了。2.3 页面结构的基本约定为了让后面的案例都能跑起来我们约定一个最简的HTML骨架。一个div容器里面放几个按钮和几个方块方便演示选择器、事件和动画。这个骨架在后续案例中会反复用到你可以先把它存成一个模板文件。!DOCTYPE html html langzh-CN head meta charsetUTF-8 titlejQuery练习/title style .box { width: 80px; height: 80px; background: #4a90d9; margin: 10px; display: inline-block; } .active { background: #e74c3c; } /style /head body div idapp button idbtn-add添加方块/button button idbtn-toggle切换颜色/button button idbtn-animate移动方块/button div idstage/div /div script srchttps://cdn.example.com/jquery-3.7.1.min.js/script script // 你的代码写在这里 /script /body /html这个骨架里#stage是方块们的“舞台”三个按钮分别触发不同的行为。CSS里定义了.box的默认样式和.active的高亮样式。后面所有案例都基于这个结构来扩展。3. 选择器与DOM操作jQuery最核心的基本功3.1 选择器写法的“直觉化”优势jQuery的选择器语法几乎和CSS选择器一模一样这是它最讨喜的地方。你CSS里怎么写jQuery里就怎么写只是外面套了一个$()。比如$(#app)选id为app的元素$(.box)选所有class为box的元素$(div p)选div里所有的p元素。这种一致性让写惯了CSS的人几乎零成本上手。但有一个区别必须搞清楚CSS选择器返回的是一组匹配规则而jQuery选择器返回的是一个jQuery对象。这个对象像一个“包装盒”里面装着零个或多个DOM元素。你不能直接对它用原生DOM的属性和方法比如.innerHTML、.style得用jQuery提供的方法比如.html()、.css()。这个“包装盒”的概念是理解jQuery一切操作的基础。我见过不少新手写出$(.box).innerHTML xxx这样的代码然后发现没效果就是因为把jQuery对象当成了原生DOM元素。正确的写法是$(.box).html(xxx)。记住jQuery对象是“批量操作”的你调一个方法它会对里面所有元素都执行一遍这比原生遍历方便太多。3.2 增删改查四类操作的实战演示我们用前面搭好的骨架来演示DOM的增删改查。先看“增”点击“添加方块”按钮往#stage里追加一个新的.box元素。$(#btn-add).on(click, function() { var $newBox $(div classbox/div); $(#stage).append($newBox); });这里$(div classbox/div)是jQuery的“创建元素”语法传入一段HTML字符串它会帮你生成对应的jQuery对象。然后.append()把它追加到#stage内部末尾。整个过程不需要document.createElement也不需要appendChild一行搞定。再看“删”给每个方块加一个点击删除的功能。这里用到了jQuery的事件委托因为方块是动态添加的直接给.box绑事件对后添加的元素无效。$(#stage).on(click, .box, function() { $(this).remove(); });$(this)在事件回调里指向被点击的那个方块.remove()把它从DOM里彻底移除。注意.remove()和.detach()的区别.remove()会同时移除元素上绑定的事件和数据.detach()则保留方便之后重新插入。练习阶段用.remove()就够了。“改”的操作最典型的是改样式和改内容。点击“切换颜色”按钮让所有方块在默认色和高亮色之间切换$(#btn-toggle).on(click, function() { $(#stage .box).toggleClass(active); });.toggleClass()是jQuery里非常好用的一个方法有则删、无则加省去了自己写if-else判断的麻烦。改内容用.text()或.html()前者只处理文本后者会解析HTML标签。安全起见如果内容来自用户输入优先用.text()避免XSS风险。“查”的操作包括获取元素数量、遍历元素、筛选元素。比如$(#stage .box).length能拿到当前方块的数量$(#stage .box).each(function(index, el){ ... })能遍历每个方块。.each()的回调里this指向当前原生DOM元素$(this)才是jQuery对象这个细节要分清。3.3 链式调用的原理与书写习惯jQuery最优雅的设计之一就是链式调用。你可以把多个操作串在一行里$(#stage) .append(div classbox/div) .find(.box) .addClass(active) .css(border-radius, 8px);能这样写的原因是大部分jQuery方法执行完后返回的还是当前jQuery对象或经过筛选后的新jQuery对象所以可以继续点下去。但要注意不是所有方法都返回jQuery对象。比如.text()不带参数时返回字符串.val()不带参数时返回表单值这些“取值”操作会中断链式调用。写链式调用时把“设置”类操作放前面“取值”类操作放最后或者用变量接一下。链式调用虽然爽但别写太长。超过五六个操作串在一起调试起来会很痛苦报错时你都不知道是哪一环出的问题。我的习惯是超过四个操作就换行并且用变量把中间结果存一下可读性优先。4. 事件处理机制从绑定到委托的完整链路4.1 on方法的多副面孔jQuery的事件绑定核心就是.on()这一个方法。它有三种常见用法对应不同的场景。第一种直接绑定$(#btn-add).on(click, handler)。这是最基础的用法给已存在的元素绑事件。第二种绑定多个事件$(#btn-add).on(click mouseenter, handler)事件名用空格隔开一个回调处理多个事件。第三种事件委托$(#stage).on(click, .box, handler)把事件绑在父元素上通过第二个参数指定“真正触发事件的子元素选择器”。事件委托是jQuery里极其重要的一个机制它的原理是事件会从触发元素向上冒泡到父元素父元素上的监听器检查事件目标是否匹配选择器匹配就执行回调。这个机制解决了两个大问题一是动态添加的元素自动拥有事件不需要重新绑定二是减少了事件监听器的数量性能更好。前面删除方块的例子用的就是委托。4.2 事件对象与阻止默认行为事件回调函数接收一个参数通常命名为e或event这就是jQuery封装过的事件对象。它有几个常用的属性和方法e.target是实际触发事件的元素e.currentTarget是绑定事件的元素在委托场景下两者不同e.preventDefault()阻止默认行为e.stopPropagation()阻止冒泡。一个典型场景点击链接时不想跳转只执行自定义逻辑。用e.preventDefault()就能阻止默认的跳转行为。再比如嵌套元素都绑了点击事件你只想让最内层的生效用e.stopPropagation()阻止事件继续向上冒泡。注意在事件委托场景下e.currentTarget指向的是绑定事件的那个父元素而不是被点击的子元素。如果你需要操作被点击的子元素用$(e.target)或者回调里的$(this)。这个区别在调试时经常让人困惑记住就好。4.3 事件解绑与一次性事件.off()用来解绑事件用法和.on()对应。$(#btn-add).off(click)解绑所有click事件$(#btn-add).off(click, handler)只解绑指定的回调。实际项目中解绑常用于组件销毁时清理资源避免内存泄漏。.one()是绑定一次性事件的方法触发一次后自动解绑。比如某个引导提示只显示一次用.one(click, ...)就很合适省去了手动.off()的步骤。还有一个容易忽略的点jQuery的事件系统是独立于原生addEventListener的。如果你用原生方式绑了事件用jQuery的.off()是解绑不掉的反之亦然。混用时要注意要么统一用jQuery要么统一用原生别两边混着来。5. 动画与效果让页面“动起来”的几种手段5.1 内置动画方法的参数详解jQuery内置了一批动画方法最常用的有.show()、.hide()、.toggle()、.fadeIn()、.fadeOut()、.slideDown()、.slideUp()。这些方法都接受三个可选参数持续时间、缓动函数、回调函数。持续时间可以是毫秒数如400也可以是预设字符串slow对应600毫秒fast对应200毫秒。缓动函数默认是swing另一种是linear。swing是先快后慢再快看起来更自然linear是匀速。回调函数在动画结束后执行常用来做下一步操作。$(#stage .box).fadeOut(400, swing, function() { console.log(淡出完成); });这里有个坑如果对一组元素调用动画方法回调函数会对每个元素都执行一次而不是整组动画结束后执行一次。如果你只想在所有动画完成后执行一次得用.promise()配合.done()或者自己计数。这个细节在批量动画时特别容易出问题。5.2 animate方法实现自定义动画内置方法不够用时.animate()可以自定义CSS属性的过渡效果。它接受一个属性对象、持续时间、缓动函数和回调。$(#btn-animate).on(click, function() { $(#stage .box).animate({ marginLeft: 200px, opacity: 0.5 }, 600, swing, function() { $(this).animate({ marginLeft: 10px, opacity: 1 }, 600); }); });这段代码让方块先向右移动并变半透明完成后又移回原位并恢复不透明。.animate()能动画的属性必须是数值型的比如width、height、margin、opacity、left、top等。颜色类属性如background-color默认不支持需要额外插件。还有一个重要概念动画队列。jQuery会把同一个元素上的动画按调用顺序排成队列前一个动画完成后才执行下一个。如果你连续调用多次.animate()它们会依次执行。但如果你在动画进行中又调了一次新动画会排到队列末尾而不是打断当前动画。想打断当前动画立即执行新的用.stop()。.stop()有两个参数是否清空队列、是否跳到当前动画的终点。.stop(true, true)是最常用的组合清空队列并立即完成当前动画。5.3 动画性能的实战经验jQuery的动画本质上是定时器不断修改元素的CSS样式属于JavaScript驱动的动画。这种方式在元素少、动画简单时没问题但元素一多或者动画复杂就容易掉帧。我的经验是能用CSS3 transition和animation实现的优先用CSS3性能好得多。jQuery动画适合做那些需要动态计算、或者需要兼容老环境的场景。另外动画属性尽量选transform和opacity这两个属性不会触发页面重排性能最好。用.animate()直接改left、top、width、height会触发重排元素多了会卡。如果非要用.animate()改位置可以考虑用margin代替left或者用CSS3的transform配合jQuery的.css()来设置。6. 综合案例一个可交互的方块管理面板6.1 需求拆解与实现思路把前面学的选择器、DOM操作、事件、动画串起来做一个完整的小面板。需求是这样的页面上有一个“添加方块”按钮点击后往舞台里加一个方块每个方块点击后高亮再点取消高亮双击方块把它删除还有一个“全部清除”按钮点击后所有方块淡出并移除。另外显示一个计数器实时显示当前方块数量。这个案例覆盖了jQuery的大部分核心操作动态创建元素、事件委托、类切换、动画、DOM遍历、文本更新。实现思路是用一个renderCount()函数统一更新计数器在添加和删除方块后都调用它。方块的高亮用.toggleClass(active)删除用.fadeOut()加回调里的.remove()保证动画播完再移除。6.2 完整代码与逐段解析$(function() { var $stage $(#stage); var $count $(span idcount0/span); $(#app).prepend($count); function renderCount() { $count.text($stage.find(.box).length); } $(#btn-add).on(click, function() { $(div classbox/div).appendTo($stage); renderCount(); }); $stage.on(click, .box, function() { $(this).toggleClass(active); }); $stage.on(dblclick, .box, function() { $(this).fadeOut(300, function() { $(this).remove(); renderCount(); }); }); $(#btn-clear).on(click, function() { $stage.find(.box).fadeOut(300, function() { $(this).remove(); renderCount(); }); }); renderCount(); });逐段看。$(function(){ ... })是$(document).ready()的简写确保DOM加载完成后再执行代码。$count是动态创建的计数器元素用.prepend()插到#app最前面。renderCount()每次重新统计.box数量并更新文本简单可靠。添加方块用$(div classbox/div).appendTo($stage)注意这里用的是.appendTo()而不是.append()方向反过来了.append()是“把参数加到我这”.appendTo()是“把我加到参数那”。两者效果一样看个人习惯。双击删除用.fadeOut(300, callback)回调里先.remove()再renderCount()。这里有个顺序问题如果先renderCount()再.remove()计数会多算一个因为元素还在DOM里。所以必须移除后再统计。“全部清除”用$stage.find(.box)选中所有方块批量淡出。注意回调会对每个方块执行一次所以renderCount()会被调用多次但每次统计结果都一样因为所有方块都在同一批动画里被移除最终结果正确只是有点浪费。想优化的话可以用.promise().done()但练习阶段没必要。6.3 从案例中提炼的通用模式这个案例里藏着几个可以复用的模式。第一个是“动态元素用事件委托”所有绑定在.box上的事件都委托给了$stage这样后添加的方块自动拥有事件。第二个是“动画后操作放回调”删除元素前先播动画动画结束的回调里再真正移除。第三个是“状态更新函数化”把计数逻辑抽成renderCount()哪里需要哪里调避免散落在各处。还有一个细节$stage.on(click, .box, ...)和$stage.on(dblclick, .box, ...)可以合并成一次绑定吗可以用$stage.on(click dblclick, .box, handler)然后在handler里用e.type判断事件类型。但这样代码可读性会下降我倾向于分开写清晰。7. 练习中容易踩的坑与排查思路7.1 选择器返回空对象却不报错jQuery最“坑”新手的一点是$(.not-exist)不会报错它返回一个空的jQuery对象你调任何方法都不报错只是什么都不发生。这跟原生document.querySelector(.not-exist)返回null然后你调.style就报错的行为完全不同。好处是代码不会崩坏处是出了问题你很难发现。排查这类问题的第一步永远是console.log($(.not-exist).length)看是不是0。如果是0说明选择器没选到东西检查类名拼写、元素是否已渲染、选择器路径是否正确。我见过有人把.box写成.Box大小写不一致排查半天。7.2 事件绑定失效的三种常见原因事件绑了没反应通常逃不出三个原因。第一元素是动态添加的你用了直接绑定而不是委托。解决办法是把事件绑到静态父元素上用委托语法。第二代码执行时元素还没渲染出来$(.box)选到的是空集。解决办法是把代码放进$(function(){})里或者用委托。第三事件被其他元素的stopPropagation拦截了或者被preventDefault阻止了默认行为。用浏览器的开发者工具看事件监听器能快速定位。7.3 动画队列堆积导致的行为异常连续快速点击“移动方块”按钮你会发现方块移动得越来越慢或者行为变得诡异。这是因为每次点击都往动画队列里塞了一个新动画队列越排越长。解决办法是在动画前先.stop(true, true)清空队列并立即完成当前动画。$(#btn-animate).on(click, function() { $(#stage .box).stop(true, true).animate({ marginLeft: 200px }, 600); });.stop()不加参数时只停止当前动画不清空队列也不跳到终点。.stop(true)清空队列但不跳终点。.stop(true, true)清空队列并跳终点。实际用的时候.stop(true, true)最符合直觉用户再点一次当前动画立即完成然后开始新动画不会堆积。7.4 this指向混乱的典型场景在jQuery回调里this的指向取决于回调的类型。事件回调里this指向触发事件的DOM元素委托场景下是匹配选择器的那个元素。.each()回调里this指向当前遍历的DOM元素。动画回调里this指向正在动画的DOM元素。但如果你在回调里再嵌套一个普通函数那个函数里的this就变成window了。解决办法是在进入嵌套函数之前用var self this或者var $this $(this)把引用存下来。或者用ES6的箭头函数箭头函数不绑定自己的this会继承外层的this。但注意jQuery的事件回调不建议用箭头函数因为箭头函数里的this不是DOM元素会导致$(this)失效。8. 从jQuery练习中真正该带走的能力练完这些案例你手上多了几个能跑的demo但比demo更重要的是背后那套思维方式。jQuery教会我的第一件事是“批量操作”的思维选一组元素统一处理而不是一个个循环。这个思维在后来用任何框架时都用得上。第二件事是“事件委托”的思维把监听器放在稳定的父级让动态子元素自动继承行为这个模式在React、Vue的事件处理里同样存在。第三件事是“链式调用”背后的接口设计哲学每个方法返回可继续操作的对象让代码像流水线一样顺畅。jQuery本身可能不会再是你项目里的主力工具但这些底层的手感和模式认知会一直跟着你。我到现在偶尔还会用jQuery快速写个页面原型或者给老项目打补丁那种“打开编辑器就能写、不用配环境”的轻快感是很多现代工具给不了的。如果你正在学前端花一个下午把这些案例敲一遍绝对值。
阅读完成 · 觉得有帮助?
咨询建站