Vue.js实现列表数值按时段计算并展示平均值求助
Vue.js 实时货币价格平均值计算问题修复
我正在开发一个Vue.js项目,通过Coinbase API每隔1分钟获取货币价格并存入amountList数组,需要实现以下功能:
- 计算最近5分钟(数组中最后5个值)、30分钟(最后30个值)、60分钟(最后60个值)的价格平均值;
- 在三个独立区域分别展示对应时段的平均值。
当前代码无法正确实现需求,原代码如下:
原模板代码
<template> <div id="app" > <form> <label>Enter Currency: <input type="text" v-model="currency"></label> <input id="clickMe" type="button" value="Submit" @click="getData(currency) "/> </form> <pre></pre><p>Bitcoin Value is : {{ apiData?.data?.amount }}</p> <template v-for="value in getShortList(5)"> <pre></pre><p>Last 5 minute value is : {{ }} </p> <li class="divider" role="presentation"></li> </template> <template v-for="item in getShortList(29)"> <pre></pre><p>Last 30 minute value is : {{parseInt (getShortList(29))}}</p> <li class="divider" role="presentation"></li> </template> <template v-for="item in getShortList(59)"> <pre></pre><p>Last 60 minute value is : {{ parseInt (getShortList(59)) }}</p> <li class="divider" role="presentation"></li> </template> <template> <div> <apexchart width="500" type="bar" :options="options" :series="amountList"></apexchart> </div> </template> </div> </template>
原脚本代码
import axios from 'axios' export default { data() { return { apiEndPoint : 'https://api.coinbase.com/v2/prices/spot?currency=', apiData: [], amountList: [], } }, created () { this.getData(this.currency); }, methods: { getShortList(shortListSize) { return this.amountList.slice(0, shortListSize); }, getData(currency) { axios.get(`${this.apiEndPoint}${currency}`).then((response) => { this.timer = setInterval(() => { this.apiData = response.data this.amountList.push(response.data.data.amount) console.log(this.amountList) }, 5000) }) } } }
问题分析与修复步骤
初始化缺失与定时器逻辑错误
data中未定义currency,导致created钩子调用getData时参数无效;- 原定时器内未重新发起API请求,始终使用第一次请求的结果,且间隔设置为5秒(需求是1分钟);
- 需在定时器内重复调用API,同时修正间隔为60000毫秒。
数组切片方向错误
getShortList使用slice(0, size)取的是数组最前面的旧数据,而最近的数据应该用slice(-size)取数组末尾的最新值。
平均值计算逻辑缺失
- 新增计算平均值的方法,将指定数量的价格转换为数字后求和再取平均。
模板渲染逻辑错误
- 无需用
v-for循环展示平均值,直接调用计算方法即可; - 修正
apiData初始值为null,避免类型错误。
- 无需用
内存泄漏防护
- 在组件销毁时清除定时器,防止内存泄漏。
修复后的完整代码
模板部分
<template> <div id="app"> <form> <label>Enter Currency: <input type="text" v-model="currency"></label> <input id="clickMe" type="button" value="Submit" @click="startFetching(currency)" /> </form> <p>Current {{ currency }} Value: {{ apiData?.data?.amount }}</p> <div class="average-section"> <p>Last 5 Minutes Average: {{ calculateAverage(5) }}</p> <li class="divider" role="presentation"></li> </div> <div class="average-section"> <p>Last 30 Minutes Average: {{ calculateAverage(30) }}</p> <li class="divider" role="presentation"></li> </div> <div class="average-section"> <p>Last 60 Minutes Average: {{ calculateAverage(60) }}</p> <li class="divider" role="presentation"></li> </div> <div> <apexchart width="500" type="bar" :options="options" :series="formatChartData()"></apexchart> </div> </div> </template>
脚本部分
import axios from 'axios' export default { data() { return { apiEndPoint: 'https://api.coinbase.com/v2/prices/spot?currency=', apiData: null, amountList: [], currency: '', timer: null } }, beforeUnmount() { // 清除定时器防止内存泄漏 if (this.timer) { clearInterval(this.timer) } }, methods: { getRecentPrices(size) { // 取数组末尾的最新size个值 return this.amountList.slice(-size) }, calculateAverage(size) { const recentPrices = this.getRecentPrices(size) if (recentPrices.length === 0) return 'N/A' // 转换为数字并计算平均值,保留两位小数 const sum = recentPrices.reduce((total, price) => total + parseFloat(price), 0) return (sum / recentPrices.length).toFixed(2) }, async fetchPrice(currency) { try { const response = await axios.get(`${this.apiEndPoint}${currency}`) this.apiData = response.data this.amountList.push(response.data.data.amount) // 限制数组长度,只保留最近60条数据(对应60分钟) if (this.amountList.length > 60) { this.amountList.shift() } } catch (error) { console.error('Failed to fetch price:', error) } }, startFetching(currency) { // 先清除之前的定时器 if (this.timer) { clearInterval(this.timer) } this.currency = currency // 立即获取一次数据 this.fetchPrice(currency) // 设置1分钟间隔的定时器 this.timer = setInterval(() => { this.fetchPrice(currency) }, 60000) }, formatChartData() { // 适配apexchart的series格式 return [{ name: `${this.currency} Price`, data: this.amountList.map(price => parseFloat(price)) }] } } }
关键改进点
- 新增
fetchPrice方法封装API请求逻辑,确保每次定时器触发都重新获取最新价格; calculateAverage方法负责计算指定时段的平均值,保留两位小数;- 限制
amountList长度不超过60,避免数组无限增长; - 组件销毁时清除定时器,防止内存泄漏;
- 修正图表数据格式,适配apexchart要求的数组结构。
内容的提问来源于stack exchange,提问作者takis Paras
相关产品推荐
相关产品推荐

