AJAX 异步请求 + DOM 动态更新实现页面局部刷新
以Django框架下的电商平台的个人中心为例,个人中心可能会包含订单列表,收货地址管理,购物车列表等页面,为了优化页面样式以及用户交互体验,常常会设计出能够实现局部刷新的导航栏,如下:

如果仅仅为导航部分设计<a>标签跳转,每次点击都会刷新整个页面,大大降低用户使用体验。要实现个人信息页面左侧导航栏的局部刷新功能,可采用 AJAX 异步请求 + DOM 动态更新 的方式,避免整页刷新。
1. 模板优化
优化导航栏中的a标签。添加data-url存储目标URL,添加.nav-link类。
<!-- 示例:在左侧导航中修改 -->
<ul class="space-y-1">
<li>
<!-- 添加data-url存储目标URL -->
<a href="{% url 'users:user_profile' %}"
class="nav-link flex items-center px-4 py-3 text-primary bg-primary/10 rounded-lg transition-colors"
data-url="{% url 'users:user_profile' %}">
<i class="fa fa-user-o w-5 text-center mr-3"></i>
<span>个人信息</span>
</a>
</li>
<li>
<a href="{% url 'users:my_orders' %}"
class="nav-link flex items-center px-4 py-3 text-neutral-700 hover:bg-neutral-100 rounded-lg transition-colors"
data-url="{% url 'users:my_orders' %}">
<i class="fa fa-list-alt w-5 text-center mr-3"></i>
<span>我的订单</span>
</a>
</li>
<!-- 其他导航项类似修改 -->
</ul>
为主内容区域添加id标识。
<!-- 主内容区容器 -->
<div class="lg:col-span-3 space-y-8" id="main-content"> <!-- 此处新添加id属性 -->
<!-- 原内容将被动态替换 -->
</div>
创建主内容的片段模板,也就是需要被刷新的片段部分。
<!-- 主内容区容器内包含的内容 -->
<div>
此处省略
</div>
2. 添加AJAX脚本
在模板中引入 AJAX 处理脚本(可写在base.html基础模板中),实现点击导航后局部刷新:
<script>
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', function() {
// 获取所有导航链接
const navLinks = document.querySelectorAll('.nav-link');
// 获取主内容容器
const mainContent = document.getElementById('main-content');
// 为每个导航链接添加点击事件
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault(); // 阻止默认跳转
const targetUrl = this.getAttribute('data-url'); // 获取目标URL
// 显示加载状态(可选)
mainContent.innerHTML = '<div class="p-8 text-center"><i class="fa fa-spinner fa-spin text-primary text-2xl"></i><p class="mt-2">加载中...</p></div>';
// 发送AJAX请求,确保添加X-Requested-With头
fetch(targetUrl, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (!response.ok) throw new Error('请求失败');
return response.text(); // 获取HTML片段
})
.then(html => {
// 更新主内容区
mainContent.innerHTML = html;
// 更新URL但不刷新页面
history.pushState({}, '', targetUrl);
// 更新导航激活状态
navLinks.forEach(l => l.classList.remove('text-primary', 'bg-primary/10'));
this.classList.add('text-primary', 'bg-primary/10');
// 重新触发动画(如果需要)
mainContent.querySelectorAll('.fade-in').forEach(el => {
el.classList.remove('visible');
setTimeout(() => el.classList.add('visible'), 10);
});
})
.catch(error => {
mainContent.innerHTML = '<div class="p-8 text-center text-red-500">加载失败,请重试</div>';
console.error('Error:', error);
});
});
});
});
</script>
3. 后端优化
如果是AJAX请求则会返回响应的主内容的局部页面模板,AJAX脚本会通过这个局部模板进行局部刷新加载内容。
from django.shortcuts import render
from django.http import HttpResponse
def user_profile(request):
# 判断是否为AJAX请求(通过请求头或参数)
is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
if is_ajax:
# 返回局部模板
return render(request, 'users/profile_partial.html')
else:
# 返回完整页面
return render(request, 'users/user_profile.html')
# 其他视图函数处理类似....
发表评论