计算并显示 Vue Vuetify 数据中数组中每个对象的百分比差异 table
Calculate and display percentage difference for every object in an array in Vue Vuetify data table
我正在接收来自 JSON 文件的数据,如下所示:
{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}
我稍后在 Vuetify table 中显示此数据,我想要实现的是用我的百分比计算逻辑填充 thirtyDaysDiff
列。我的逻辑有效,字段被填充,但我必须为数组中的每个对象手动编写它,这是我想避免的。
如何为数组中的每个对象应用以下逻辑,而不是为每个对象手动执行?
逻辑:
calculateThirtyDayDifference() {
let calculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[0]['7d'] - this.bitcoinInfo[0]['30d'] ) / ( (this.bitcoinInfo[0]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let roundedCalculatedPercent = Math.max( Math.round(calculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[0].thirtyDaysDiff = roundedCalculatedPercent
let secondCalculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[1]['7d'] - this.bitcoinInfo[1]['30d'] ) / ( (this.bitcoinInfo[1]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let secondRoundedCalculatedPercent = Math.max( Math.round(secondCalculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[1].thirtyDaysDiff = secondRoundedCalculatedPercent
}
我试着用 forEach
来做,但没用。这是我的整个组件:
<template>
<div>
<v-data-table
:headers="headers"
:items="bitcoinInfo"
:hide-default-footer="true"
:class="{active: group && item.id == group.id}"
>
</v-data-table>
</div>
</template>
<script>
import axios from 'axios';
export default {
data () {
return {
bitcoinInfo: [],
headers: [
{
text: 'Currency',
align: 'start',
value: 'currency',
},
{ text: '30 Days Ago', value: '30d' },
{ text: '30 Day Diff %', value: 'thirtyDaysDiff'},
{ text: '7 Days Ago', value: '7d' },
{ text: '7 Day Diff %', value: 'sevenDaysDifference' },
{ text: '24 Hours Ago', value: '24h' },
],
}
},
methods: {
getBitcoinData() {
axios
.get('data.json')
.then((response => {
var convertedCollection = Object.keys(response.data).map(key => {
return {currency: key, thirtyDaysDiff: 0, sevenDaysDifference: 0, ...response.data[key]}
})
this.bitcoinInfo = convertedCollection
}))
.catch(err => console.log(err))
},
calculateThirtyDayDifference() {
let calculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[0]['7d'] - this.bitcoinInfo[0]['30d'] ) / ( (this.bitcoinInfo[0]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let roundedCalculatedPercent = Math.max( Math.round(calculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[0].thirtyDaysDiff = roundedCalculatedPercent
let secondCalculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[1]['7d'] - this.bitcoinInfo[1]['30d'] ) / ( (this.bitcoinInfo[1]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let secondRoundedCalculatedPercent = Math.max( Math.round(secondCalculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[1].thirtyDaysDiff = secondRoundedCalculatedPercent
}
},
mounted() {
this.getBitcoinData()
},
updated() {
this.calculateThirtyDayDifference()
}
}
</script>
我建议使用插槽,并计算动态显示的值。
Vuetify 允许您使用插槽自定义特定列单元格的呈现
item.<column-key-name>
(我更喜欢使用 #slotName
语法,但您也可以使用 v-slot:slotName
):
<template #item.thirtyDaysDiff="{ item }">
{{ calculateThirtyDayDifference(item) }}%
</template>
这允许我们将每一行的数据(通过插槽的 item
属性)提供给计算函数,然后通过简单地为每一行调用该函数来显示每一行的计算值。
以这种方式使用函数的缺点是它会在每次渲染时被重新调用和重新计算,但对于不应导致任何性能的简单计算问题。
这是一个使用您的测试数据的功能齐全的示例:
new Vue({
// ## Required for snippet only ##
el: '#app', template: '#app-template', vuetify: new Vuetify(),
// #########
data() {
return {
bitcoinInfo: [],
headers: [{text:"Currency",align:"start",value:"currency"},{text:"30 Days Ago",value:"30d"},{text:"30 Day Diff %",value:"thirtyDaysDiff"},{text:"7 Days Ago",value:"7d"},{text:"7 Day Diff %",value:"sevenDaysDifference"},{text:"24 Hours Ago",value:"24h"}],
}
},
methods: {
calculateThirtyDayDifference(item) {
let calculatedPercent = 100 * Math.abs((item['7d'] - item['30d']) / ((item['7d'] + item['30d']) / 2));
return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
}
},
computed: {
thirtyDayDiffArray() {
return 1;
},
},
mounted() {
// Load sample data
let sampleData = JSON.parse('{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}');
this.bitcoinInfo = Object.keys(sampleData)
.map(key => ({
currency: key,
sevenDaysDifference: 0,
...sampleData[key]
})
);
},
})
<!-- Import Vuetify and Vue for snippet -->
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"><script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<!-- Target container for Vue to render into -->
<div id="app"></div>
<!-- Template that Vue will use -->
<script type="text/x-template" id="app-template">
<v-app>
<v-data-table
:headers="headers"
:items="bitcoinInfo"
:hide-default-footer="true"
>
<template #item.thirtyDaysDiff="{ item }">
{{ calculateThirtyDayDifference(item) }}%
</template>
</v-data-table>
</v-app>
</script>
我正在接收来自 JSON 文件的数据,如下所示:
{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}
我稍后在 Vuetify table 中显示此数据,我想要实现的是用我的百分比计算逻辑填充 thirtyDaysDiff
列。我的逻辑有效,字段被填充,但我必须为数组中的每个对象手动编写它,这是我想避免的。
如何为数组中的每个对象应用以下逻辑,而不是为每个对象手动执行?
逻辑:
calculateThirtyDayDifference() {
let calculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[0]['7d'] - this.bitcoinInfo[0]['30d'] ) / ( (this.bitcoinInfo[0]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let roundedCalculatedPercent = Math.max( Math.round(calculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[0].thirtyDaysDiff = roundedCalculatedPercent
let secondCalculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[1]['7d'] - this.bitcoinInfo[1]['30d'] ) / ( (this.bitcoinInfo[1]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let secondRoundedCalculatedPercent = Math.max( Math.round(secondCalculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[1].thirtyDaysDiff = secondRoundedCalculatedPercent
}
我试着用 forEach
来做,但没用。这是我的整个组件:
<template>
<div>
<v-data-table
:headers="headers"
:items="bitcoinInfo"
:hide-default-footer="true"
:class="{active: group && item.id == group.id}"
>
</v-data-table>
</div>
</template>
<script>
import axios from 'axios';
export default {
data () {
return {
bitcoinInfo: [],
headers: [
{
text: 'Currency',
align: 'start',
value: 'currency',
},
{ text: '30 Days Ago', value: '30d' },
{ text: '30 Day Diff %', value: 'thirtyDaysDiff'},
{ text: '7 Days Ago', value: '7d' },
{ text: '7 Day Diff %', value: 'sevenDaysDifference' },
{ text: '24 Hours Ago', value: '24h' },
],
}
},
methods: {
getBitcoinData() {
axios
.get('data.json')
.then((response => {
var convertedCollection = Object.keys(response.data).map(key => {
return {currency: key, thirtyDaysDiff: 0, sevenDaysDifference: 0, ...response.data[key]}
})
this.bitcoinInfo = convertedCollection
}))
.catch(err => console.log(err))
},
calculateThirtyDayDifference() {
let calculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[0]['7d'] - this.bitcoinInfo[0]['30d'] ) / ( (this.bitcoinInfo[0]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let roundedCalculatedPercent = Math.max( Math.round(calculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[0].thirtyDaysDiff = roundedCalculatedPercent
let secondCalculatedPercent = 100 * Math.abs( ( this.bitcoinInfo[1]['7d'] - this.bitcoinInfo[1]['30d'] ) / ( (this.bitcoinInfo[1]['7d']+this.bitcoinInfo[0]['30d'])/2 ) )
let secondRoundedCalculatedPercent = Math.max( Math.round(secondCalculatedPercent * 10) / 10, 2.8 ).toFixed(2)
this.bitcoinInfo[1].thirtyDaysDiff = secondRoundedCalculatedPercent
}
},
mounted() {
this.getBitcoinData()
},
updated() {
this.calculateThirtyDayDifference()
}
}
</script>
我建议使用插槽,并计算动态显示的值。
Vuetify 允许您使用插槽自定义特定列单元格的呈现
item.<column-key-name>
(我更喜欢使用 #slotName
语法,但您也可以使用 v-slot:slotName
):
<template #item.thirtyDaysDiff="{ item }">
{{ calculateThirtyDayDifference(item) }}%
</template>
这允许我们将每一行的数据(通过插槽的 item
属性)提供给计算函数,然后通过简单地为每一行调用该函数来显示每一行的计算值。
以这种方式使用函数的缺点是它会在每次渲染时被重新调用和重新计算,但对于不应导致任何性能的简单计算问题。
这是一个使用您的测试数据的功能齐全的示例:
new Vue({
// ## Required for snippet only ##
el: '#app', template: '#app-template', vuetify: new Vuetify(),
// #########
data() {
return {
bitcoinInfo: [],
headers: [{text:"Currency",align:"start",value:"currency"},{text:"30 Days Ago",value:"30d"},{text:"30 Day Diff %",value:"thirtyDaysDiff"},{text:"7 Days Ago",value:"7d"},{text:"7 Day Diff %",value:"sevenDaysDifference"},{text:"24 Hours Ago",value:"24h"}],
}
},
methods: {
calculateThirtyDayDifference(item) {
let calculatedPercent = 100 * Math.abs((item['7d'] - item['30d']) / ((item['7d'] + item['30d']) / 2));
return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
}
},
computed: {
thirtyDayDiffArray() {
return 1;
},
},
mounted() {
// Load sample data
let sampleData = JSON.parse('{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}');
this.bitcoinInfo = Object.keys(sampleData)
.map(key => ({
currency: key,
sevenDaysDifference: 0,
...sampleData[key]
})
);
},
})
<!-- Import Vuetify and Vue for snippet -->
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"><link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"><script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<!-- Target container for Vue to render into -->
<div id="app"></div>
<!-- Template that Vue will use -->
<script type="text/x-template" id="app-template">
<v-app>
<v-data-table
:headers="headers"
:items="bitcoinInfo"
:hide-default-footer="true"
>
<template #item.thirtyDaysDiff="{ item }">
{{ calculateThirtyDayDifference(item) }}%
</template>
</v-data-table>
</v-app>
</script>