第七章:jQuery的辉煌——DOM操作的王者

“没有jQuery的时代,前端工程师是用牙啃DOM的。”

墨尘的这句话让林小凡差点把嘴里的泡面喷出来。

他正对着一个古董级企业网站抓耳挠腮——这个用jQuery 1.3.2写的项目突然被甲方要求“现代化改造”,而文档里只有一行README:

“别动,能跑就行。”

“这代码……像用象形文字写的。”林小凡颤抖着点开main.js,映入眼帘的是:

javascript 复制代码
$('#main-content')
    .find('.widget:visible')
    .not(':has(.hidden)')
    .each(function() {
        $(this).hover(
            function() { $(this).addClass('active').siblings().fadeTo(200, 0.5); },
            function() { $(this).removeClass('active').siblings().fadeTo(200, 1); }
        );
    });

他试着在控制台输入$('#main-content')——

一个熟悉的蓝底白字错误跳出来:

$ is not defined

“哈!果然连jQuery都没引入!”他得意地准备加上<script src="jquery.js">,却被墨尘的消息打断:

“先别急,看看Network面板。”

林小凡打开开发者工具,赫然发现页面底部藏着:

html 复制代码
<script src="/libs/jquery-1.3.2.min.js" defer></script>
<script src="/js/legacy-polyfill.js"></script>

那个legacy-polyfill.js里赫然写着:

javascript 复制代码
// 防止$冲突
jQuery.noConflict();
var $jq = jQuery;

“所以……”林小凡声音发抖,“这个项目里$不是jQuery?!”

**“欢迎来到2010年的前端地狱。”**墨尘回复道。


第一节:选择器之王

为了理解这段“考古发现”,林小凡决定系统学习jQuery。

他打开2006年的教程视频,画面里一个兴奋的程序员演示着:

javascript 复制代码
// 原生JS获取所有.red元素
var redElements = document.querySelectorAll('.red'); // 2013年才普及

// jQuery方式
var $redElements = $('.red');

“就这?”林小凡不以为然,“现在用document.querySelectorAll不就行了?”

直到他看到下一个例子:

javascript 复制代码
// 原生JS切换类
var element = document.getElementById('menu');
if (element.classList.contains('active')) { // IE9+才支持classList
    element.classList.remove('active');
} else {
    element.classList.add('active');
}

// jQuery方式
$('#menu').toggleClass('active');

视频里的讲师激情解说:“jQuery让DOM操作像说话一样自然!

林小凡突然理解了为什么这个库能统治前端十年——在IE6还是主流浏览器的年代,原生DOM API简直是刑具。


第二节:链式调用的魔法

随着深入学习,林小凡被jQuery的链式调用震撼了:

javascript 复制代码
$('.item')
    .filter(':odd')
    .css('color', 'red')
    .end()
    .find('.icon')
    .attr('title', 'Modified!');

这种流畅的操作让他想起自己用现代JS写的臃肿代码:

javascript 复制代码
document.querySelectorAll('.item').forEach((el, index) => {
    if (index % 2 === 1) {
        el.style.color = 'red';
    }
    el.querySelectorAll('.icon').forEach(icon => {
        icon.setAttribute('title', 'Modified!');
    });
});

“难怪老程序员提起jQuery都眼含热泪……”他喃喃自语。

墨尘发来一个jQuery时代的经典段子:

“当年面试只考两件事:你能手写AJAX吗?你能不用jQuery操作DOM吗?”


第三节:动画帝国的崛起

最让林小凡惊叹的是jQuery的动画系统。

那个古董项目里有一段神奇的代码:

javascript 复制代码
$('#banner')
    .slideDown(300)
    .delay(500)
    .animate({ 
        'margin-left': '+=200px',
        'opacity': 0.7
    }, {
        duration: 800,
        complete: function() {
            $(this).html('Animation Complete!');
        }
    });

他试着用现代CSS重写:

css 复制代码
#banner {
    transition: all 0.3s ease;
    /* 如何实现delay后的链式动画? */
}

“CSS动画没法这么精确控制流程啊!”他抓狂地发现需要嵌套setTimeout才能模拟。

墨尘适时补刀:

“知道为什么当年jQuery UI能火了吧?那可是在CSS3诞生前的黑暗年代。”


第四节:插件生态的狂欢

林小凡在代码深处发现了一个神秘引用:

html 复制代码
<script src="/libs/jquery.mousewheel.min.js"></script>
<script src="/libs/jquery.cookie.min.js"></script>
<script src="/libs/jquery.validate.min.js"></script>

这些插件让他窥见jQuery全盛时期的生态:

  • 表单验证不用写正则表达式(jQuery Validation)
  • 轮播图不用算偏移量(Slick Slider)
  • 模态框不用调z-index(Magnific Popup)

“这不就是现代npm生态的雏形吗?!”林小凡恍然大悟。

直到他尝试升级jQuery版本……


第五节:版本升级的血泪

“我就想升级到jQuery 3.0……”林小凡委屈地看着满屏报错。

问题接踵而至:

  1. $.browser被移除(旧代码里全是IE6判断)
  2. animate()scrollTop语法变了
  3. load()事件被on('load')取代

最致命的是某个插件报错:

javascript 复制代码
// 某神秘插件内部
$.fn.hover = function(fn1, fn2) {
    return this.on('mouseenter', fn1).on('mouseleave', fn2 || fn1);
};

而jQuery 3.0+已经内置了更科学的.hover()方法。

“所以现在怎么办?”林小凡绝望地问。

墨尘发来一个链接:

jQuery Migrate Plugin

“用这个过渡,或者……”

“重写整个项目。”


终节:王者的黄昏

深夜,林小凡终于让古董网站在jQuery 3.6.0下跑起来了。

他翻看着Git提交历史,最早的记录停在2009年:

bash 复制代码
commit 3a1b5c8 (HEAD -> master)
Author: Unknown <old_dev@example.com>
Date:   Mon Aug 3 14:22:38 2009 +0800

    初次提交:基于jQuery 1.3.2的企业门户

十四年前的代码,至今仍在线上运行。

他突然理解了jQuery的伟大——它用简单的$()统一了碎片化的浏览器世界,让Web开发从刀耕火种进入铁器时代。

关掉电脑前,他鬼使神差地在控制台输入:

javascript 复制代码
$.fn.jquery // "3.6.0"

蓝色的版本号在黑暗中闪烁,像一座纪年碑。

第七章 完


下一章预告:
第八章:Angular的崛起——MVC的革新
“当jQuery开发者第一次看到ng-repeat时,他们的表情就像看到火器的原始人。”——某前端历史学家