AJAX 异步请求 + DOM 动态更新实现页面局部刷新


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')

# 其他视图函数处理类似....

0 条评论

发表评论

暂无评论,欢迎发表您的观点!