下载工作台
jQuery 与 Layui 实战

jQuery Ajax 与数据交互

试读上半部分 · 解锁后可读全文

第 4 章 · jQuery Ajax 与数据交互

本章目标:掌握 $.ajax 完整参数$.get / $.post / $.getJSON;对比 Fetch API;实现 加载状态与错误处理;在 Django 后台场景正确提交 CSRF Token;为 admin-demo 对接模拟商品列表接口。

学时建议:5~6 小时(含 2 小时跟练)

前置:jquery-layui ch01~ch03;frontend-web ch12(Fetch、async/await)。


4.1 $.ajax 完整参数

$.ajax({
  url: '/api/admin/products/',
  type: 'GET',              // 或 method: 'GET'(1.9+)
  data: { page: 1, size: 20, keyword: '示例' },
  dataType: 'json',         // 期望响应类型:json / html / text
  timeout: 10000,           // 毫秒
  cache: false,             // GET 防缓存
  headers: {
    'X-Requested-With': 'XMLHttpRequest'
  },
  beforeSend: function (xhr) {
    $('#product-tbody').addClass('is-loading');
  },
  success: function (data, textStatus, xhr) {
    renderProductTable(data.results || data);
  },
  error: function (xhr, textStatus, errorThrown) {
    var msg = xhr.responseJSON && xhr.responseJSON.message
      ? xhr.responseJSON.message
      : '请求失败:' + xhr.status;
    showToast(msg, 'error');
  },
  complete: function () {
    $('#product-tbody').removeClass('is-loading');
  }
});
参数说明
url请求地址
type / methodHTTP 动词
data查询串或对象;对象默认 application/x-www-form-urlencoded
contentType默认 application/x-www-form-urlencoded; charset=UTF-8
processData是否序列化 data;上传 FormData 时设 false
dataType自动解析 json;设 json 时非法 JSON 走 error
traditional数组序列化方式(与 Django 列表参数相关)

4.2 简写方法

// GET
$.get('/api/admin/products/', { page: 1 }, function (data) {
  console.log(data);
});

// POST
$.post('/api/admin/products/', { name: '新品', price: 99 }, function (res) {
  console.log(res.id);
});

// 只取 JSON
$.getJSON('/api/admin/products/stats.json', function (stats) {
  $('#stat-orders').text(stats.order_count);
});
方法等价
$.get(url, data, success)$.ajax GET
$.post(url, data, success)$.ajax POST
$.getJSON(url, success)GET + dataType: 'json'

Promise 风格(jQuery 3+ 原生;1.12 可用 $.Deferred):

// 1.12  Deferred
var req = $.get('/api/admin/products/');
req.done(function (data) { /* ... */ });
req.fail(function (xhr) { /* ... */ });

4.3 与 Fetch 对比

维度jQuery $.ajaxFetch
浏览器支持需引入 jQuery现代浏览器原生
JSON 解析dataType: 'json' 自动res.json()
超时timeout 内置AbortController
进度xhr 对象有限
错误HTTP 4xx/5xx 仍可能进 success(看 dataType)res.ok 需手动判断
取消xhr.abort()AbortController
// Fetch(frontend-web ch12)
async function loadProductsFetch() {
  const res = await fetch('/api/admin/products/?page=1');
  if (!res.ok) throw new Error('HTTP ' + res.status);
  return res.json();
}

// jQuery 等价
function loadProductsJq() {
  return $.getJSON('/api/admin/products/', { page: 1 });
}

行业常见策略:存量 Layui / jQuery 页继续 $.ajax;新 Vue 模块用 axios / Fetch。维护老后台必须熟悉 $.ajax


4.4 加载状态与错误处理

4.4.1 全局 Ajax 事件

$(document)
  .ajaxStart(function () {
    $('#global-loading').show();
  })
  .ajaxStop(function () {
    $('#global-loading').hide();
  })
  .ajaxError(function (event, xhr, settings, thrown) {
    console.error(settings.url, thrown);
  });
全局事件触发时机
ajaxStart / ajaxStop任意 Ajax 开始 / 全部结束
ajaxSend单个请求发送前
ajaxComplete单个请求完成(含失败)
ajaxSuccess单个成功
ajaxError单个失败

4.4.2 统一封装(admin-demo)

var Api = {
  request: function (options) {
    var defaults = {
      type: 'GET',
      dataType: 'json',
      timeout: 15000
    };
    var opts = $.extend({}, defaults, options);

    return $.ajax(opts).then(
      function (data) {
        if (data && data.code !== undefined && data.code !== 0) {
          return $.Deferred().reject(data).promise();
        }
        return data.data !== undefined ? data.data : data;
      },
      function (xhr) {
        var body = xhr.responseJSON || {};
        var message = body.message || '网络异常,请稍后重试';
        showToast(message, 'error');
        return $.Deferred().reject(xhr).promise();
      }
    );
  },

  getProducts: function (params) {
    return this.request({ url: '/api/admin/products/', data: params });
  }
};

响应约定(与常见 REST 封装对齐):

{
  "code": 0,
  "message": "ok",
  "data": {
    "results": [],
    "total": 0
  }
}

4.5 Django CSRF Token 提交

Django 对 POST/PUT/DELETE 等变更请求校验 CSRF。jQuery 需在请求头或表单字段携带 token。

4.5.1 从 Cookie 读取(推荐)

function getCookie(name) {
  var match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));
  return match ? decodeURIComponent(match[1]) : null;
}

function csrfSafeMethod(method) {
  return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method);
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type)) {
      xhr.setRequestHeader('X-CSRFToken', getCookie('csrftoken'));
    }
  }
});

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。