如何优化EJS页面表格列平均值计算代码并生成柱状图?
优化方案:后端用MongoDB Aggregate计算平均值(推荐)
直接在数据库层面完成平均值计算,既能消除前端重复循环的冗余代码,还能减少前端需要处理的数据量。
1. 修改Express路由,使用aggregate()
替换原有find()查询,通过MongoDB聚合管道直接计算4个数值列的全局平均值:
// 假设你的4个数值列字段为:price、batteryLife、screenSize、cameraMP router.get('/phones', async (req, res) => { try { // 聚合计算各列平均值 const avgResult = await Phone.aggregate([ { $group: { _id: null, // 不分组,计算全表平均值 avgPrice: { $avg: '$price' }, avgBattery: { $avg: '$batteryLife' }, avgScreen: { $avg: '$screenSize' }, avgCamera: { $avg: '$cameraMP' } } } ]); // 获取原始数据用于表格展示 const phones = await Phone.find(); // 将平均值和原始数据一同传入EJS模板 res.render('phones', { phones, averages: avgResult[0] }); } catch (err) { console.error(err); res.status(500).send('服务器错误'); } });
后端直接返回计算好的平均值,前端无需再做任何循环计算,彻底解决代码冗余问题。
前端优化方案(无需修改后端时)
如果暂时不想调整后端逻辑,可将重复的循环计算封装为通用函数,避免代码重复:
1. 封装平均值计算函数
在EJS模板的<script>标签或独立JS文件中定义通用函数:
<script> function getColumnAverage(dataList) { if (!dataList.length) return 0; const total = dataList.reduce((sum, val) => sum + val, 0); return (total / dataList.length).toFixed(2); // 保留两位小数 } </script>
2. 调用函数计算各列平均值
在EJS中收集每列数据后,统一调用函数计算:
<% // 收集各列数据 const priceList = phones.map(item => item.price); const batteryList = phones.map(item => item.batteryLife); const screenList = phones.map(item => item.screenSize); const cameraList = phones.map(item => item.cameraMP); // 计算平均值 const avgPrice = getColumnAverage(priceList); const avgBattery = getColumnAverage(batteryList); const avgScreen = getColumnAverage(screenList); const avgCamera = getColumnAverage(cameraList); %>
无论后续新增多少数值列,只需复用该函数即可,避免重复编写循环逻辑。
页面底部实现柱状图
以本地引入的Chart.js为例(无需外链,将Chart.js文件放在项目静态资源目录),实现平均值柱状图:
1. 添加Canvas容器
<div style="width: 80%; margin: 2rem auto;"> <canvas id="averageChart"></canvas> </div>
2. 初始化柱状图
如果使用后端返回的averages数据:
<script src="/js/chart.min.js"></script> <!-- 本地引入Chart.js文件 --> <script> const chartCtx = document.getElementById('averageChart').getContext('2d'); new Chart(chartCtx, { type: 'bar', data: { labels: ['价格', '电池续航', '屏幕尺寸', '摄像头像素'], datasets: [{ label: '各列平均值', data: [ <%= averages.avgPrice %>, <%= averages.avgBattery %>, <%= averages.avgScreen %>, <%= averages.avgCamera %> ], backgroundColor: [ 'rgba(255, 99, 132, 0.6)', 'rgba(54, 162, 235, 0.6)', 'rgba(255, 206, 86, 0.6)', 'rgba(75, 192, 192, 0.6)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)' ], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); </script>
若使用前端计算的平均值,将data数组中的值替换为对应的前端变量即可。
内容的提问来源于stack exchange,提问作者Bartek
相关产品推荐
相关产品推荐

