最可靠方案是用 $.ajaxprefilter 或 beforesend 拦截原生 xhr:前者适用于全局 jquery 请求(含 layui 内部 ajax),后者专用于 table.render 且能操作原始 xhr 实例;二者均可动态读取最新 token,避免 $.ajaxsetup 的静态覆盖与污染问题。
直接用 $.ajaxsetup 最快,但会污染所有 jquery 请求;真正可靠且不影响表单提交、表格分页等行为的方案,是用 $.ajaxprefilter 或 beforesend 拦截原生 xhr —— 后者更适合 table 组件。
$.ajaxSetup 为什么慎用
它会让所有 $.get、$.post、form.on('submit') 甚至 Layui 内部调用的 AJAX 都带上 headers,但问题在于:
- 无法动态读取
localStorage.getItem('token')——$.ajaxSetup初始化时就固定了值,token 刷新后不会自动更新 - 如果某次请求明确传了
headers,会被$.ajaxSetup覆盖,反而出错 -
form.on('submit')默认是页面跳转,不是 AJAX,所以它根本不受$.ajaxSetup影响(除非你手动改成$.post)
$.ajaxPrefilter 是更干净的选择
它在每次请求发出前执行,能读最新 token,且只影响 jQuery 的 AJAX 行为(Layui table/form 的内部请求也走这条链路):
layui.use('jquery', function(){
var $ = layui.jquery;
$.ajaxPrefilter(function(options, originalOptions, jqXHR){
var token = localStorage.getItem('access_token');
if (token) {
options.headers = options.headers || {};
options.headers.Authorization = 'Bearer ' + token;
// 如果后端要的是 X-Access-Token,就写成:
// options.headers['X-Access-Token'] = token;
}
});
});
注意点:
- 必须在
layui.use里调用,确保$是 Layui 封装过的 jQuery 实例 - 不要在
$.ajaxSetup和$.ajaxPrefilter里同时设 headers,否则可能冲突 -
$.ajaxPrefilter不会影响layer.open里 iframe 加载页面这类非 AJAX 行为
table.render 的 headers 必须用 beforeSend
table.render({ headers: { ... } }) 是无效写法 —— Layui 2.8.x 及之前版本压根不支持这个配置项。唯一有效方式是通过 beforeSend 注入原生 XHR:
table.render({
elem: '#demo',
url: '/api/users',
method: 'get',
beforeSend: function(xhr) {
var token = localStorage.getItem('access_token');
if (token) {
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
}
},
parseData: function(res) {
if (res.code === 401) {
localStorage.removeItem('access_token');
location.href = '/login';
return { count: 0, data: [] };
}
return { count: res.total, data: res.data };
}
});
关键细节:
-
beforeSend是 table 唯一能拿到原始XMLHttpRequest实例的地方 - 如果用了
method: 'post'且后端只认application/json,记得加contentType: 'application/json',否则 headers 可能被忽略 -
parseData必须自己处理 401,否则表格只会显示“数据接口请求异常”,用户完全不知道发生了什么
Token 过期和刷新的实际坑
单纯加 headers 不够,真实场景中 token 会过期、需要刷新,但 Layui 没有内置 refresh 流程:
- 别在
beforeSend里直接发刷新请求 —— 会阻塞当前请求,造成死锁 - 推荐做法:在
parseData检出 401 后,跳转登录页,或弹窗提示重新登录 - 如果要做静默刷新,得封装独立的
http.request工具函数,把 token 获取、刷新、重试逻辑收拢,而不是散落在每个table.render里 - localStorage 存 token 有风险,生产环境建议配合 httpOnly cookie + CSRF token 使用
最常被忽略的是:table 的 parseData 和 form 提交的 success/error 回调不在同一套错误处理体系里,得分别兜底。token 逻辑一旦分散,后期维护成本会指数级上升。











