jQuery進(jìn)階入門:從基礎(chǔ)到高效開發(fā)的核心突破

在掌握jQuery基礎(chǔ)選擇器、DOM操作和簡(jiǎn)單事件后,進(jìn)階的關(guān)鍵是理解“為什么這么用”和“如何更高效地用”。本文圍繞jQuery進(jìn)階開發(fā)的四大核心能力——鏈?zhǔn)秸{(diào)用原理、事件委托深化、Ajax全場(chǎng)景實(shí)戰(zhàn)、插件開發(fā)入門,通過(guò)“原理拆解+實(shí)戰(zhàn)案例+性能優(yōu)化”的結(jié)構(gòu),幫你突破基礎(chǔ)瓶頸,用jQuery解決更復(fù)雜的前端需求,同時(shí)理解背后的設(shè)計(jì)邏輯。

一、進(jìn)階核心1:吃透鏈?zhǔn)秸{(diào)用——從“會(huì)用”到“理解原理”

基礎(chǔ)開發(fā)中,我們常用$('#box').css('color','red').text('內(nèi)容')這類鏈?zhǔn)秸{(diào)用,但很少思考“為什么能鏈?zhǔn)秸{(diào)用”。理解其原理,能幫你避免鏈?zhǔn)秸{(diào)用中的常見錯(cuò)誤,甚至自定義支持鏈?zhǔn)秸{(diào)用的方法。

1. 鏈?zhǔn)秸{(diào)用的核心原理

jQuery的鏈?zhǔn)秸{(diào)用本質(zhì)是“方法執(zhí)行后返回當(dāng)前jQuery對(duì)象(this)”,而非返回undefined或其他值。例如:

// jQuery內(nèi)部方法簡(jiǎn)化邏輯

jQuery.fn.css = function(prop, value) {

? // 執(zhí)行設(shè)置樣式的邏輯...

? return this; // 關(guān)鍵:返回當(dāng)前jQuery對(duì)象

};

jQuery.fn.text = function(text) {

? // 執(zhí)行設(shè)置文本的邏輯...

? return this; // 繼續(xù)返回當(dāng)前jQuery對(duì)象

};

// 因此可鏈?zhǔn)秸{(diào)用:方法返回的對(duì)象繼續(xù)調(diào)用下一個(gè)方法

$('#box').css('color','red').text('內(nèi)容');

注意:并非所有方法都支持鏈?zhǔn)秸{(diào)用

部分方法因需要返回“具體結(jié)果”(而非jQuery對(duì)象),不支持鏈?zhǔn)秸{(diào)用,例如:

val():獲取輸入框值時(shí),返回字符串(如$('#input').val()),無(wú)法鏈?zhǔn)秸{(diào)用;

text():獲取文本時(shí),返回字符串(如$('#box').text()),無(wú)法鏈?zhǔn)秸{(diào)用;

find():返回新的jQuery對(duì)象(匹配子元素),支持鏈?zhǔn)秸{(diào)用,但操作的是新對(duì)象。

示例:鏈?zhǔn)秸{(diào)用的正確與錯(cuò)誤用法

// 正確:設(shè)置值的方法支持鏈?zhǔn)秸{(diào)用(返回jQuery對(duì)象)

$('#input')

? .val('進(jìn)階學(xué)習(xí)') // 設(shè)置值,返回jQuery對(duì)象

? .css('color','#2563eb') // 繼續(xù)操作當(dāng)前對(duì)象

? .attr('placeholder','請(qǐng)輸入內(nèi)容'); // 繼續(xù)操作

// 錯(cuò)誤:獲取值的方法不支持鏈?zhǔn)秸{(diào)用(返回字符串)

$('#input')

? .val() // 獲取值,返回字符串

? .css('color','red'); // 報(bào)錯(cuò):字符串沒(méi)有css()方法

2. 鏈?zhǔn)秸{(diào)用的進(jìn)階技巧:end()與add()

當(dāng)鏈?zhǔn)秸{(diào)用中使用find()、filter()等方法切換了操作對(duì)象后,可通過(guò)end()返回上一級(jí)對(duì)象,add()添加新的操作對(duì)象,避免重復(fù)選擇元素。

方法作用示例代碼

end()返回上一級(jí)jQuery對(duì)象$('#box').find('p').css('color','red').end().css('border','1px solid #ddd')

add()給當(dāng)前jQuery對(duì)象添加新元素$('p').add('div').css('margin','10px')

實(shí)戰(zhàn)案例:用end()簡(jiǎn)化多元素操作

<div id="box">

? <p class="item">子元素1</p>

? <p class="item">子元素2</p>

</div>

<script>

? $(function() {

? ? // 需求:給#box添加邊框,同時(shí)給內(nèi)部p標(biāo)簽設(shè)置紅色文本

? ? // 方法1:重復(fù)選擇元素(低效)

? ? $('#box').css('border', '1px solid #ddd');

? ? $('#box').find('p').css('color', 'red');

? ? // 方法2:用end()鏈?zhǔn)秸{(diào)用(高效,僅選擇一次#box)

? ? $('#box')

? ? ? .css('border', '1px solid #ddd') // 操作#box

? ? ? .find('p') // 切換到p標(biāo)簽

? ? ? .css('color', 'red') // 操作p標(biāo)簽

? ? ? .end(); // 返回上一級(jí)#box(若后續(xù)需繼續(xù)操作#box)

? });

</script>

二、進(jìn)階核心2:事件委托深化——解決動(dòng)態(tài)元素與性能問(wèn)題

基礎(chǔ)開發(fā)中,我們常用click()直接綁定事件,但面對(duì)“動(dòng)態(tài)生成的元素”或“大量元素”時(shí),這種方式會(huì)失效或?qū)е滦阅軉?wèn)題。進(jìn)階的關(guān)鍵是掌握on()方法的事件委托機(jī)制。

1. 為什么需要事件委托?

直接綁定事件(如$('.item').click())的兩大問(wèn)題:

動(dòng)態(tài)元素?zé)o效:事件綁定在初始元素上,后續(xù)動(dòng)態(tài)添加的元素不會(huì)繼承事件;

性能開銷大:若有1000個(gè).item元素,會(huì)綁定1000個(gè)事件處理函數(shù),占用大量?jī)?nèi)存。

事件委托的原理是“將事件綁定在靜態(tài)父元素上,通過(guò)事件冒泡觸發(fā)”,只需綁定1個(gè)事件,即可處理所有子元素的事件,包括動(dòng)態(tài)添加的子元素。

2. 事件委托的正確語(yǔ)法:on()的三參數(shù)用法

基礎(chǔ)綁定語(yǔ)法:$('selector').on('event', handler)(直接綁定)

事件委托語(yǔ)法:$('parentSelector').on('event', 'childSelector', handler)(委托綁定)

參數(shù)位置作用說(shuō)明

第一個(gè)參數(shù)事件名(如'click'、'input')支持多個(gè)事件,用空格分隔(如'click mouseenter')

第二個(gè)參數(shù)子元素選擇器(委托目標(biāo))必須是父元素的子元素,動(dòng)態(tài)添加的子元素也會(huì)生效

第三個(gè)參數(shù)事件處理函數(shù)函數(shù)中的this指向子元素(委托目標(biāo))

實(shí)戰(zhàn)案例1:處理動(dòng)態(tài)元素事件

<ul id="list">

? <!-- 初始元素 -->

? <li class="item">初始項(xiàng)1</li>

? <li class="item">初始項(xiàng)2</li>

<?href="zhiq.zhaopin.com/moment/82695346 ?">

<?href="zhiq.zhaopin.com/moment/82695381 ?">

<?href="zhiq.zhaopin.com/moment/82695400 ?">

<?href="zhiq.zhaopin.com/moment/82695413 ?">

<?href="zhiq.zhaopin.com/moment/82695426 ?">

<?href="zhiq.zhaopin.com/moment/82695442 ?">

<?href="zhiq.zhaopin.com/moment/82695450 ?">

<?href="zhiq.zhaopin.com/moment/82695452 ?">

<?href="zhiq.zhaopin.com/moment/82695457 ?">

<?href="zhiq.zhaopin.com/moment/82695461 ?">

</ul>

<button id="addItem">添加新項(xiàng)</button>

<script>

? $(function() {

? ? // 1. 錯(cuò)誤:直接綁定事件,動(dòng)態(tài)添加的項(xiàng)無(wú)效

? ? // $('.item').click(function() {

? ? //? alert($(this).text());

? ? // });

? ? // 2. 正確:事件委托,綁定在靜態(tài)父元素#list上

? ? $('#list').on('click', '.item', function() {

? ? ? alert($(this).text()); // this指向被點(diǎn)擊的.item(包括動(dòng)態(tài)添加的)

? ? });

? ? // 動(dòng)態(tài)添加項(xiàng)

? ? $('#addItem').click(function() {

? ? ? const newItem = $(`<li class="item">動(dòng)態(tài)項(xiàng)${$('#list .item').length + 1}</li>`);

? ? ? $('#list').append(newItem);

? ? });

? });

</script>

實(shí)戰(zhàn)案例2:優(yōu)化大量元素事件性能

<!-- 假設(shè)有100個(gè)列表項(xiàng) -->

<ul id="bigList">

? <!-- 100個(gè)<li class="item">...</li> -->

</ul>

<script>

? $(function() {

? ? // 1. 低效:直接綁定,創(chuàng)建100個(gè)事件處理函數(shù)

? ? // $('#bigList .item').click(function() {

? ? //? $(this).toggleClass('active');

? ? // });

? ? // 2. 高效:事件委托,僅創(chuàng)建1個(gè)事件處理函數(shù)

? ? $('#bigList').on('click', '.item', function() {

? ? ? $(this).toggleClass('active');

? ? });

? });

</script>

3. 事件委托的進(jìn)階技巧:事件數(shù)據(jù)與阻止冒泡

(1)傳遞事件數(shù)據(jù)

通過(guò)on()的第二個(gè)參數(shù)(或第三個(gè)參數(shù),取決于是否委托)傳遞數(shù)據(jù),在事件處理函數(shù)中通過(guò)event.data獲取,避免使用全局變量。

// 傳遞數(shù)據(jù):給事件處理函數(shù)傳遞用戶ID

$('#userList').on('click', '.user-item', { role: 'admin' }, function(event) {

? const userId = $(this).data('user-id');

? const userRole = event.data.role; // 獲取傳遞的數(shù)據(jù)

? console.log(`用戶ID:${userId},角色:${userRole}`);

});

(2)阻止事件冒泡與默認(rèn)行為

在事件委托中,若需要阻止事件冒泡(避免父元素事件觸發(fā))或阻止默認(rèn)行為(如鏈接跳轉(zhuǎn)),需在事件處理函數(shù)中使用event.stopPropagation()和event.preventDefault()。

<div id="outer">

? <a class="link">jQuery官網(wǎng)</a>

</div>

<script>

? $(function() {

? ? // 父元素事件

? ? $('#outer').on('click', function() {

? ? ? alert('點(diǎn)擊了外層div');

? ? });

? ? // 子元素事件委托,阻止冒泡和默認(rèn)行為

? ? $('#outer').on('click', '.link', function(event) {

? ? ? event.stopPropagation(); // 阻止事件冒泡,外層div事件不觸發(fā)

? ? ? event.preventDefault(); // 阻止默認(rèn)行為,鏈接不跳轉(zhuǎn)

? ? ? alert('點(diǎn)擊了鏈接,但不跳轉(zhuǎn)');

? ? });

? });

</script>

三、進(jìn)階核心3:Ajax全場(chǎng)景實(shí)戰(zhàn)——從基礎(chǔ)請(qǐng)求到復(fù)雜交互

jQuery的Ajax模塊是其核心優(yōu)勢(shì)之一,基礎(chǔ)開發(fā)中可能用過(guò)$.get()或$.post(),但進(jìn)階開發(fā)需要掌握更靈活的$.ajax()方法,處理“請(qǐng)求參數(shù)、響應(yīng)解析、錯(cuò)誤處理、加載狀態(tài)”等全場(chǎng)景需求。

1. jQuery Ajax的核心方法對(duì)比

jQuery提供了多個(gè)Ajax相關(guān)方法,不同方法適用于不同場(chǎng)景:

方法作用適用場(chǎng)景語(yǔ)法示例

$.get(url, data, success)發(fā)送GET請(qǐng)求(獲取數(shù)據(jù))簡(jiǎn)單數(shù)據(jù)獲?。ㄈ缌斜頂?shù)據(jù))$.get('/api/list', { page: 1 }, function(res) { ... })

$.post(url, data, success)發(fā)送POST請(qǐng)求(提交數(shù)據(jù))簡(jiǎn)單數(shù)據(jù)提交(如表單提交)$.post('/api/login', { username: 'admin' }, function(res) { ... })

$.ajax(options)通用Ajax方法(支持所有配置)復(fù)雜需求(如文件上傳、超時(shí)設(shè)置)$.ajax({ url: '/api/data', type: 'GET', ... })

2.$.ajax()全配置實(shí)戰(zhàn):處理復(fù)雜請(qǐng)求

$.ajax()通過(guò)配置對(duì)象支持“請(qǐng)求類型、參數(shù)、響應(yīng)類型、超時(shí)、錯(cuò)誤處理”等所有Ajax需求,是進(jìn)階開發(fā)的首選方法。

核心配置項(xiàng)說(shuō)明

配置項(xiàng)類型作用示例值

urlString請(qǐng)求地址/api/user

typeString請(qǐng)求類型(GET/POST/PUT/DELETE)'POST'

dataObject/String請(qǐng)求參數(shù){ id: 1, name: 'admin' }

dataTypeString預(yù)期響應(yīng)數(shù)據(jù)類型(json/text/html)'json'(自動(dòng)解析JSON)

contentTypeString請(qǐng)求頭Content-Type'application/json'(JSON格式提交)

timeoutNumber請(qǐng)求超時(shí)時(shí)間(毫秒)5000(5秒超時(shí))

beforeSendFunction請(qǐng)求發(fā)送前執(zhí)行(如設(shè)置loading)function(xhr) { $('#loading').show(); }

successFunction請(qǐng)求成功執(zhí)行function(res) { console.log(res); }

errorFunction請(qǐng)求失敗執(zhí)行(如網(wǎng)絡(luò)錯(cuò)誤、超時(shí))function(xhr, status) { alert('請(qǐng)求失敗'); }

completeFunction請(qǐng)求完成后執(zhí)行(無(wú)論成功失?。ゝunction() { $('#loading').hide(); }

實(shí)戰(zhàn)案例1:JSON格式提交與響應(yīng)解析

<!-- 表單 -->

<form id="userForm">

? <input type="text" name="username" placeholder="用戶名">

? <input type="password" name="password" placeholder="密碼">

<?href="zhiq.zhaopin.com/moment/82695464 ?">

<?href="zhiq.zhaopin.com/moment/82695468 ?">

<?href="zhiq.zhaopin.com/moment/82695473 ?">

<?href="zhiq.zhaopin.com/moment/82695476 ?">

<?href="zhiq.zhaopin.com/moment/82695479 ?">

<?href="zhiq.zhaopin.com/moment/82695481 ?">

<?href="zhiq.zhaopin.com/moment/82695485 ?">

<?href="zhiq.zhaopin.com/moment/82695521 ?">

<?href="zhiq.zhaopin.com/moment/82695529 ?">

<?href="zhiq.zhaopin.com/moment/82695541 ?">

? <button type="submit">提交</button>

</form>

<div id="loading" style="display: none;">加載中...</div>

<script>

? $(function() {

? ? $('#userForm').on('submit', function(e) {

? ? ? e.preventDefault();

? ? ? // 1. 獲取表單數(shù)據(jù)

? ? ? const formData = {

? ? ? ? username: $('[name="username"]').val().trim(),

? ? ? ? password: $('[name="password"]').val().trim()

? ? ? };

? ? ? // 2. 發(fā)送Ajax請(qǐng)求

? ? ? $.ajax({

? ? ? ? url: '/api/login', // 實(shí)際項(xiàng)目中替換為真實(shí)接口地址

? ? ? ? type: 'POST',

? ? ? ? dataType: 'json', // 預(yù)期響應(yīng)是JSON格式

? ? ? ? contentType: 'application/json', // 請(qǐng)求體是JSON格式

? ? ? ? data: JSON.stringify(formData), // 將對(duì)象轉(zhuǎn)為JSON字符串

? ? ? ? timeout: 5000, // 5秒超時(shí)

? ? ? ? beforeSend: function() {

? ? ? ? ? // 請(qǐng)求前顯示loading

? ? ? ? ? $('#loading').show();

? ? ? ? },

? ? ? ? success: function(res) {

? ? ? ? ? // 請(qǐng)求成功:根據(jù)響應(yīng)處理

? ? ? ? ? if (res.code === 200) {

? ? ? ? ? ? alert('登錄成功!');

? ? ? ? ? ? window.location.href = '/home'; // 跳轉(zhuǎn)到首頁(yè)

? ? ? ? ? } else {

? ? ? ? ? ? alert('登錄失?。? + res.msg);

? ? ? ? ? }

? ? ? ? },

? ? ? ? error: function(xhr, status) {

? ? ? ? ? // 請(qǐng)求失?。禾幚砭W(wǎng)絡(luò)錯(cuò)誤、超時(shí)等

? ? ? ? ? if (status === 'timeout') {

? ? ? ? ? ? alert('請(qǐng)求超時(shí),請(qǐng)稍后重試');

? ? ? ? ? } else {

? ? ? ? ? ? alert('網(wǎng)絡(luò)錯(cuò)誤,請(qǐng)求失敗');

? ? ? ? ? }

? ? ? ? },

? ? ? ? complete: function() {

? ? ? ? ? // 請(qǐng)求完成:隱藏loading(無(wú)論成功失?。?/p>

? ? ? ? ? $('#loading').hide();

? ? ? ? }

? ? ? });

? ? });

? });

</script>

實(shí)戰(zhàn)案例2:文件上傳(FormData格式)

文件上傳需用FormData格式提交,$.ajax()需配置contentType: false和processData: false,避免jQuery自動(dòng)處理請(qǐng)求體。

<!-- 文件上傳表單 -->

<input type="file" id="fileInput" accept="image/*">

<button id="uploadBtn">上傳圖片</button>

<div id="progress" style="width: 300px; height: 10px; border: 1px solid #ddd; margin-top: 10px; display: none;">

? <div id="progressBar" style="width: 0; height: 100%; background: #4096ff;"></div>

</div>

<script>

? $(function() {

? ? $('#uploadBtn').click(function() {

? ? ? const file = $('#fileInput')[0].files[0]; // 獲取選擇的文件

? ? ? if (!file) {

? ? ? ? alert('請(qǐng)選擇圖片文件');

? ? ? ? return;

? ? ? }

? ? ? // 1. 創(chuàng)建FormData對(duì)象,添加文件和其他參數(shù)

? ? ? const formData = new FormData();

? ? ? formData.append('file', file); // 添加文件

? ? ? formData.append('type', 'image'); // 添加其他參數(shù)

? ? ? // 2. 發(fā)送文件上傳請(qǐng)求

? ? ? $.ajax({

? ? ? ? url: '/api/upload', // 實(shí)際項(xiàng)目中替換為真實(shí)接口地址

? ? ? ? type: 'POST',

? ? ? ? data: formData,

? ? ? ? contentType: false, // 關(guān)鍵:不設(shè)置Content-Type,由瀏覽器自動(dòng)處理

? ? ? ? processData: false, // 關(guān)鍵:不處理請(qǐng)求數(shù)據(jù)(避免將FormData轉(zhuǎn)為字符串)

? ? ? ? xhr: function() {

? ? ? ? ? // 自定義XHR對(duì)象,監(jiān)聽上傳進(jìn)度

? ? ? ? ? const xhr = $.ajaxSettings.xhr();

? ? ? ? ? if (xhr.upload) {

? ? ? ? ? ? xhr.upload.addEventListener('progress', function(e) {

? ? ? ? ? ? ? if (e.lengthComputable) {

? ? ? ? ? ? ? ? const percent = Math.round((e.loaded / e.total) * 100); // 計(jì)算上傳進(jìn)度

? ? ? ? ? ? ? ? $('#progress').show();

? ? ? ? ? ? ? ? $('#progressBar').css('width', percent + '%');

? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? ? }

? ? ? ? ? return xhr;

? ? ? ? },

? ? ? ? success: function(res) {

? ? ? ? ? if (res.code === 200) {

? ? ? ? ? ? alert('上傳成功!圖片地址:' + res.data.url);

? ? ? ? ? ? $('#progressBar').css('width', '100%');

? ? ? ? ? } else {

? ? ? ? ? ? alert('上傳失?。? + res.msg);

? ? ? ? ? }

? ? ? ? },

? ? ? ? error: function() {

? ? ? ? ? alert('上傳失敗,請(qǐng)稍后重試');

? ? ? ? }

? ? ? });

? ? });

? });

</script>

3. Ajax進(jìn)階技巧:全局事件與請(qǐng)求攔截

(1)全局Ajax事件

jQuery提供全局Ajax事件,可在所有Ajax請(qǐng)求中統(tǒng)一</doubaocanvas>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容