云浮市文章资讯

Ajax免刷新地前后端交互功能实例

2026-03-27 11:11:04 浏览次数:0
详细信息

1. 前端HTML页面 (index.html)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ajax 无刷新交互示例</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Microsoft YaHei', sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }

        .container {
            background: white;
            border-radius: 10px;
            padding: 30px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 15px;
            border-bottom: 2px solid #4CAF50;
        }

        .section {
            margin: 25px 0;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 8px;
            background: #fafafa;
        }

        h2 {
            color: #4CAF50;
            margin-bottom: 15px;
        }

        .input-group {
            margin-bottom: 15px;
        }

        label {
            display: block;
            margin-bottom: 5px;
            color: #555;
            font-weight: bold;
        }

        input, textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
        }

        textarea {
            height: 100px;
            resize: vertical;
        }

        button {
            background: #4CAF50;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background 0.3s;
        }

        button:hover {
            background: #45a049;
        }

        .loading {
            display: none;
            color: #2196F3;
            margin: 10px 0;
        }

        .result {
            margin-top: 15px;
            padding: 15px;
            border-radius: 4px;
            background: #e8f5e8;
            border-left: 4px solid #4CAF50;
            display: none;
        }

        .result.error {
            background: #ffebee;
            border-left-color: #f44336;
        }

        #userList {
            list-style: none;
            margin: 10px 0;
        }

        #userList li {
            padding: 10px;
            margin: 5px 0;
            background: white;
            border: 1px solid #ddd;
            border-radius: 4px;
            display: flex;
            justify-content: space-between;
        }

        .delete-btn {
            background: #f44336;
            padding: 5px 10px;
            font-size: 12px;
        }

        .delete-btn:hover {
            background: #d32f2f;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Ajax 无刷新交互演示</h1>

        <!-- 用户注册部分 -->
        <div class="section">
            <h2>1. 用户注册</h2>
            <div class="input-group">
                <label for="username">用户名:</label>
                <input type="text" id="username" placeholder="请输入用户名">
            </div>
            <div class="input-group">
                <label for="email">邮箱:</label>
                <input type="email" id="email" placeholder="请输入邮箱">
            </div>
            <button id="registerBtn">注册用户</button>
            <div class="loading" id="registerLoading">注册中...</div>
            <div class="result" id="registerResult"></div>
        </div>

        <!-- 获取用户列表 -->
        <div class="section">
            <h2>2. 用户列表</h2>
            <button id="getUsersBtn">获取用户列表</button>
            <div class="loading" id="usersLoading">加载中...</div>
            <ul id="userList"></ul>
            <div class="result" id="usersResult"></div>
        </div>

        <!-- 数据提交 -->
        <div class="section">
            <h2>3. 提交数据</h2>
            <div class="input-group">
                <label for="dataInput">输入内容:</label>
                <textarea id="dataInput" placeholder="请输入要提交的内容"></textarea>
            </div>
            <button id="submitDataBtn">提交数据</button>
            <div class="loading" id="submitLoading">提交中...</div>
            <div class="result" id="submitResult"></div>
        </div>

        <!-- 模拟搜索 -->
        <div class="section">
            <h2>4. 实时搜索</h2>
            <div class="input-group">
                <label for="searchInput">搜索关键词:</label>
                <input type="text" id="searchInput" placeholder="输入关键词开始搜索">
            </div>
            <div class="loading" id="searchLoading">搜索中...</div>
            <div id="searchResults"></div>
        </div>
    </div>

    <script>
        // 基础配置
        const API_BASE = 'http://localhost:3000/api';

        // 显示/隐藏加载动画
        function showLoading(elementId) {
            document.getElementById(elementId).style.display = 'block';
        }

        function hideLoading(elementId) {
            document.getElementById(elementId).style.display = 'none';
        }

        // 显示结果
        function showResult(elementId, message, isError = false) {
            const element = document.getElementById(elementId);
            element.textContent = message;
            element.className = isError ? 'result error' : 'result';
            element.style.display = 'block';

            // 3秒后自动隐藏
            setTimeout(() => {
                element.style.display = 'none';
            }, 3000);
        }

        // 1. 注册用户
        document.getElementById('registerBtn').addEventListener('click', function() {
            const username = document.getElementById('username').value.trim();
            const email = document.getElementById('email').value.trim();

            if (!username || !email) {
                showResult('registerResult', '请输入用户名和邮箱', true);
                return;
            }

            showLoading('registerLoading');

            // 使用Fetch API发送POST请求
            fetch(`${API_BASE}/register`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    username: username,
                    email: email
                })
            })
            .then(response => response.json())
            .then(data => {
                hideLoading('registerLoading');
                if (data.success) {
                    showResult('registerResult', `注册成功!用户ID: ${data.user.id}`);
                    // 清空输入框
                    document.getElementById('username').value = '';
                    document.getElementById('email').value = '';
                    // 刷新用户列表
                    loadUsers();
                } else {
                    showResult('registerResult', data.message || '注册失败', true);
                }
            })
            .catch(error => {
                hideLoading('registerLoading');
                showResult('registerResult', '请求失败: ' + error.message, true);
            });
        });

        // 2. 获取用户列表
        function loadUsers() {
            showLoading('usersLoading');

            // 使用XMLHttpRequest(传统方式)
            const xhr = new XMLHttpRequest();
            xhr.open('GET', `${API_BASE}/users`, true);

            xhr.onload = function() {
                hideLoading('usersLoading');
                if (xhr.status === 200) {
                    const data = JSON.parse(xhr.responseText);
                    displayUsers(data.users || []);
                } else {
                    showResult('usersResult', '获取用户列表失败', true);
                }
            };

            xhr.onerror = function() {
                hideLoading('usersLoading');
                showResult('usersResult', '网络错误', true);
            };

            xhr.send();
        }

        function displayUsers(users) {
            const userList = document.getElementById('userList');
            userList.innerHTML = '';

            if (users.length === 0) {
                userList.innerHTML = '<li>暂无用户</li>';
                return;
            }

            users.forEach(user => {
                const li = document.createElement('li');
                li.innerHTML = `
                    <span>${user.username} (${user.email})</span>
                    <button class="delete-btn" onclick="deleteUser(${user.id})">删除</button>
                `;
                userList.appendChild(li);
            });
        }

        // 删除用户
        window.deleteUser = function(userId) {
            if (!confirm('确定要删除这个用户吗?')) return;

            fetch(`${API_BASE}/users/${userId}`, {
                method: 'DELETE'
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    loadUsers(); // 重新加载列表
                }
            })
            .catch(error => {
                console.error('删除失败:', error);
            });
        };

        document.getElementById('getUsersBtn').addEventListener('click', loadUsers);

        // 3. 提交数据
        document.getElementById('submitDataBtn').addEventListener('click', function() {
            const data = document.getElementById('dataInput').value.trim();

            if (!data) {
                showResult('submitResult', '请输入内容', true);
                return;
            }

            showLoading('submitLoading');

            // 使用Fetch API
            fetch(`${API_BASE}/submit`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ data: data })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('网络响应异常');
                }
                return response.json();
            })
            .then(data => {
                hideLoading('submitLoading');
                showResult('submitResult', `提交成功!服务器返回: ${data.message}`);
                document.getElementById('dataInput').value = '';
            })
            .catch(error => {
                hideLoading('submitLoading');
                showResult('submitResult', '提交失败: ' + error.message, true);
            });
        });

        // 4. 实时搜索
        let searchTimeout;
        document.getElementById('searchInput').addEventListener('input', function() {
            const keyword = this.value.trim();

            clearTimeout(searchTimeout);

            if (keyword.length === 0) {
                document.getElementById('searchResults').innerHTML = '';
                return;
            }

            if (keyword.length < 2) return;

            showLoading('searchLoading');

            // 防抖处理,300毫秒后执行搜索
            searchTimeout = setTimeout(() => {
                // 使用jQuery风格的ajax(如果引入jQuery)
                // 这里使用原生的fetch
                fetch(`${API_BASE}/search?q=${encodeURIComponent(keyword)}`)
                .then(response => response.json())
                .then(data => {
                    hideLoading('searchLoading');
                    displaySearchResults(data.results || []);
                })
                .catch(error => {
                    hideLoading('searchLoading');
                    console.error('搜索失败:', error);
                });
            }, 300);
        });

        function displaySearchResults(results) {
            const container = document.getElementById('searchResults');

            if (results.length === 0) {
                container.innerHTML = '<p>没有找到相关结果</p>';
                return;
            }

            let html = '<h3>搜索结果:</h3><ul>';
            results.forEach(result => {
                html += `<li><strong>${result.title}</strong>: ${result.content}</li>`;
            });
            html += '</ul>';

            container.innerHTML = html;
        }

        // 页面加载时获取用户列表
        document.addEventListener('DOMContentLoaded', loadUsers);
    </script>
</body>
</html>

2. 后端Node.js服务器 (server.js)

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
const PORT = 3000;

// 中间件
app.use(cors()); // 允许跨域
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// 模拟数据库
let users = [
    { id: 1, username: '张三', email: 'zhangsan@example.com' },
    { id: 2, username: '李四', email: 'lisi@example.com' },
    { id: 3, username: '王五', email: 'wangwu@example.com' }
];

let userIdCounter = 4;

// 模拟搜索数据
const searchData = [
    { id: 1, title: 'JavaScript教程', content: '学习JavaScript基础知识' },
    { id: 2, title: 'Ajax技术', content: '掌握Ajax异步通信' },
    { id: 3, title: 'Node.js开发', content: '使用Node.js构建服务器' },
    { id: 4, title: '前端框架', content: 'React、Vue等框架使用' },
    { id: 5, title: '数据库操作', content: 'MongoDB和MySQL的使用' }
];

// API路由

// 1. 用户注册
app.post('/api/register', (req, res) => {
    const { username, email } = req.body;

    if (!username || !email) {
        return res.json({
            success: false,
            message: '用户名和邮箱不能为空'
        });
    }

    // 检查邮箱是否已存在
    const emailExists = users.some(user => user.email === email);
    if (emailExists) {
        return res.json({
            success: false,
            message: '邮箱已存在'
        });
    }

    // 创建新用户
    const newUser = {
        id: userIdCounter++,
        username,
        email,
        createdAt: new Date().toISOString()
    };

    users.push(newUser);

    res.json({
        success: true,
        message: '注册成功',
        user: newUser
    });
});

// 2. 获取用户列表
app.get('/api/users', (req, res) => {
    res.json({
        success: true,
        users: users
    });
});

// 3. 删除用户
app.delete('/api/users/:id', (req, res) => {
    const userId = parseInt(req.params.id);
    const initialLength = users.length;

    users = users.filter(user => user.id !== userId);

    if (users.length < initialLength) {
        res.json({
            success: true,
            message: '用户删除成功'
        });
    } else {
        res.json({
            success: false,
            message: '用户不存在'
        });
    }
});

// 4. 提交数据
app.post('/api/submit', (req, res) => {
    const { data } = req.body;

    if (!data) {
        return res.status(400).json({
            success: false,
            message: '数据不能为空'
        });
    }

    // 模拟处理数据
    const processedData = data.toUpperCase();

    res.json({
        success: true,
        message: `已收到数据: ${data}`,
        processed: processedData,
        timestamp: new Date().toISOString()
    });
});

// 5. 搜索功能
app.get('/api/search', (req, res) => {
    const query = req.query.q || '';

    if (!query) {
        return res.json({
            success: true,
            results: []
        });
    }

    const keyword = query.toLowerCase();
    const results = searchData.filter(item => 
        item.title.toLowerCase().includes(keyword) || 
        item.content.toLowerCase().includes(keyword)
    );

    // 模拟延迟
    setTimeout(() => {
        res.json({
            success: true,
            query: query,
            results: results,
            count: results.length
        });
    }, 500); // 500毫秒延迟
});

// 6. 获取服务器状态
app.get('/api/status', (req, res) => {
    res.json({
        success: true,
        status: '运行中',
        timestamp: new Date().toISOString(),
        usersCount: users.length
    });
});

// 静态文件服务
app.use(express.static('public'));

// 错误处理中间件
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({
        success: false,
        message: '服务器内部错误',
        error: process.env.NODE_ENV === 'development' ? err.message : undefined
    });
});

// 404处理
app.use((req, res) => {
    res.status(404).json({
        success: false,
        message: 'API端点不存在'
    });
});

// 启动服务器
app.listen(PORT, () => {
    console.log(`服务器运行在 http://localhost:${PORT}`);
    console.log(`API接口地址: http://localhost:${PORT}/api`);
    console.log('可用接口:');
    console.log('  POST   /api/register    - 用户注册');
    console.log('  GET    /api/users       - 获取用户列表');
    console.log('  DELETE /api/users/:id   - 删除用户');
    console.log('  POST   /api/submit      - 提交数据');
    console.log('  GET    /api/search?q=   - 搜索功能');
    console.log('  GET    /api/status      - 服务器状态');
});

3. package.json 依赖配置

{
  "name": "ajax-demo",
  "version": "1.0.0",
  "description": "Ajax无刷新交互演示",
  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "body-parser": "^1.20.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}

4. 运行步骤

创建项目目录结构:

ajax-demo/
├── index.html
├── server.js
├── package.json
└── public/
 └── (可放其他静态文件)

安装依赖:

npm install express cors body-parser
# 或
npm install

启动服务器:

node server.js
# 或使用nodemon(需要先安装)
nodemon server.js

访问应用: 打开浏览器,访问:http://localhost:3000

5. 主要功能说明

前端功能:

用户注册 - 使用Fetch API POST请求 用户列表 - 使用XMLHttpRequest GET请求 数据提交 - 使用Fetch API处理表单数据 实时搜索 - 使用防抖技术优化搜索请求

后端API接口:

POST /api/register - 用户注册 GET /api/users - 获取用户列表 DELETE /api/users/:id - 删除用户 POST /api/submit - 提交数据 GET /api/search - 搜索功能

技术特点:

这个实例完整展示了Ajax无刷新交互的完整流程,您可以直接运行和扩展使用。

相关推荐