如何在服务端构建文件读取数组并传入客户端script.js?
可行方案实现指南
方案1:EJS模板直接注入数据(适配你已尝试的技术栈)
既然你已经在用Node.js+EJS,这是最直接的实现方式,能满足「每次请求页面时服务端读取文件」的需求:
1. 服务端代码(示例:app.js)
先读取文件生成数组,再把数据传给EJS模板:
const express = require('express'); const fs = require('fs'); const app = express(); // 配置EJS模板引擎 app.set('view engine', 'ejs'); // 托管静态文件(style.css、script.js放public文件夹) app.use(express.static('public')); // 定义两个列表文件的路径 const list1Path = './list1.txt'; const list2Path = './list2.txt'; app.get('/', (req, res) => { // 读取文件并转成数组,同时过滤空行 const list_1 = fs.readFileSync(list1Path, 'utf-8') .split('\n') .filter(line => line.trim() !== ''); const list_2 = fs.readFileSync(list2Path, 'utf-8') .split('\n') .filter(line => line.trim() !== ''); // 把数组传给EJS模板 res.render('index', { list1: list_1, list2: list_2 }); }); app.listen(3000, () => console.log('服务运行在3000端口'));
2. 修改index.html为EJS模板(index.ejs)
在页面中通过EJS标签把服务端数据注入成客户端全局变量,这样script.js就能直接调用:
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="/style.css"> </head> <body> <button id="canBtn">切换列表</button> <p class="tag-line"></p> <!-- 补充原代码提到的tagLine元素 --> <section class="text-container"></section> <!-- 注入服务端数据为全局变量 --> <script> const list_1 = <%- JSON.stringify(list1) %>; const list_2 = <%- JSON.stringify(list2) %>; </script> <script src="/script.js"></script> </body> </html>
这里用<%- %>是为了输出未转义的JSON,确保能直接转为JS数组。
3. 客户端script.js(去除硬编码逻辑)
保留原有切换逻辑,直接使用全局变量:
const canBtn = document.getElementById('canBtn'); const tagLine = document.querySelector('.tag-line'); const textContainer = document.querySelector('.text-container'); let currentList = list_1; // 渲染列表的通用函数 function renderList(list) { textContainer.innerHTML = ''; // 清空容器 list.forEach(el => { const div = document.createElement('div'); div.innerText = el; textContainer.appendChild(div); }); } // 初始化渲染 canBtn.innerText = "CAN'T"; tagLine.innerText = 'I can still ...'; renderList(currentList); // 按钮切换逻辑 canBtn.addEventListener('click', () => { currentList = currentList === list_1 ? list_2 : list_1; canBtn.innerText = currentList === list_1 ? "CAN'T" : "CAN"; renderList(currentList); });
方案2:API接口+客户端Fetch(更符合单页应用异步逻辑)
如果不想依赖模板注入,也可以通过API接口返回数据,客户端异步请求,适合后续扩展:
1. 服务端添加API路由(app.js中补充)
app.get('/api/lists', (req, res) => { const list_1 = fs.readFileSync(list1Path, 'utf-8') .split('\n') .filter(line => line.trim() !== ''); const list_2 = fs.readFileSync(list2Path, 'utf-8') .split('\n') .filter(line => line.trim() !== ''); res.json({ list1: list_1, list2: list_2 }); });
2. 客户端script.js(异步请求数据)
去掉硬编码数组,改为加载页面时请求API:
const canBtn = document.getElementById('canBtn'); const tagLine = document.querySelector('.tag-line'); const textContainer = document.querySelector('.text-container'); let list_1, list_2, currentList; // 加载列表数据 async function loadLists() { try { const response = await fetch('/api/lists'); const data = await response.json(); list_1 = data.list1; list_2 = data.list2; currentList = list_1; // 初始化渲染 canBtn.innerText = "CAN'T"; tagLine.innerText = 'I can still ...'; renderList(currentList); // 绑定切换事件 canBtn.addEventListener('click', toggleList); } catch (err) { console.error('加载列表失败:', err); } } function renderList(list) { textContainer.innerHTML = ''; list.forEach(el => { const div = document.createElement('div'); div.innerText = el; textContainer.appendChild(div); }); } function toggleList() { currentList = currentList === list_1 ? list_2 : list_1; canBtn.innerText = currentList === list_1 ? "CAN'T" : "CAN"; renderList(currentList); } // 页面加载时执行 window.addEventListener('load', loadLists);
新手提示
- 读取文件时加
filter(line => line.trim() !== ''),可以避免文件末尾的空行被加入数组。 - 方案1的优势是页面加载时直接有数据,无需等待异步请求;方案2更灵活,适合后续需要动态刷新数据的场景。
- 确保静态文件(style.css、script.js)放在
public文件夹下,服务端通过app.use(express.static('public'))托管才能访问。
内容的提问来源于stack exchange,提问作者Jon Stewart
相关产品推荐
相关产品推荐

