使用Vanilla JS实现翻译下拉框联动书籍下拉框(XAMPP部署)
实现基于译本选择实时更新书籍下拉框的方案
需求说明
我使用XAMPP部署网站,已建立可正常使用的数据库连接。现有三个下拉菜单:译本(Translations)、书籍(books)、章节(chapters),所有数据均存储在数据库中。希望通过原生JavaScript,根据用户在「译本」下拉框的选择,实时查询并更新「书籍」下拉框的内容(例如:用户选择"English"后,书籍下拉框立即显示所有英文书籍)。采用fetch实现实时更新,将前端查询逻辑放在主页面,服务器端的数据库连接与查询逻辑放在单独文件中。
完整实现代码
1. 前端页面(book.html)
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>书籍选择</title> </head> <body> <!-- 译本下拉框 --> <select id="translations" onchange="fetchBooks()"> <option value="">请选择译本</option> <option value="English">English</option> <option value="Chinese">Chinese</option> <!-- 可根据数据库实际数据添加更多选项 --> </select> <!-- 书籍下拉框 --> <select id="books"> <option value="">请先选择译本</option> </select> <script> async function fetchBooks() { const selectedTranslation = document.getElementById('translations').value; const booksDropdown = document.getElementById('books'); // 未选择译本时重置下拉框 if (!selectedTranslation) { booksDropdown.innerHTML = '<option value="">请先选择译本</option>'; return; } try { // 携带译本参数发起请求,转义特殊字符避免错误 const response = await fetch(`/getBooks?translation=${encodeURIComponent(selectedTranslation)}`); if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const books = await response.json(); // 清空下拉框并添加新选项 booksDropdown.innerHTML = ''; const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = '请选择书籍'; booksDropdown.appendChild(defaultOption); books.forEach(book => { const option = document.createElement('option'); option.value = book.id; // 建议用书籍ID作为值,便于后续查询章节 option.textContent = book.name; booksDropdown.appendChild(option); }); } catch (error) { console.error('获取书籍列表失败:', error); booksDropdown.innerHTML = '<option value="">加载失败,请重试</option>'; } } </script> </body> </html>
2. 后端服务文件(server.js)
注意:需先安装依赖:npm install express mysql2,基于Node.js运行
const express = require('express'); const mysql = require('mysql2'); const path = require('path'); const app = express(); const port = 3000; // 配置XAMPP MySQL连接信息 const connection = mysql.createConnection({ host: 'localhost', user: 'root', // XAMPP默认MySQL用户名 password: '', // XAMPP默认MySQL密码为空 database: 'your_database_name' // 替换为你的数据库名 }); // 连接数据库 connection.connect(err => { if (err) { console.error('数据库连接失败:', err); return; } console.log('数据库连接成功'); }); // 托管静态文件,确保前端页面可访问 app.use(express.static(path.join(__dirname, 'public'))); // 处理书籍列表查询请求 app.get('/getBooks', (req, res) => { const selectedTranslation = req.query.translation; // 参数化查询防止SQL注入,根据实际表结构调整语句 const query = 'SELECT DISTINCT id, name FROM books WHERE translation = ?'; connection.query(query, [selectedTranslation], (err, results) => { if (err) { console.error('查询书籍失败:', err); return res.status(500).json({ error: '获取书籍列表失败' }); } res.json(results); }); }); // 启动服务器 app.listen(port, () => { console.log(`服务器运行在 http://localhost:${port}`); });
关键修改与注意事项
- 前端优化:
- 用
encodeURIComponent处理请求参数,避免特殊字符导致的请求错误 - 增加未选择译本时的重置逻辑,以及请求失败的友好提示
- 建议用书籍ID作为下拉框选项值,方便后续关联查询章节数据
- 用
- 后端修正:
- 修复原代码中固定表名的问题,改为根据译本动态筛选数据
- 使用参数化查询避免SQL注入风险
- 添加数据库连接状态日志,便于排查问题
- 配置静态文件托管,确保前端页面能被正常访问
- XAMPP配合:
- 确保XAMPP的MySQL服务处于运行状态
- 数据库表结构需与后端查询逻辑匹配(例如
books表包含id、name、translation字段)
内容的提问来源于stack exchange,提问作者adamcapjones
相关产品推荐
相关产品推荐

