如何有条件地更改Vue中td的文本颜色

How to change text color of td in Vue conditionally

我正在使用 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}}

我在 table 中显示它。我计算 7 天和 30 天的百分比变化,以及该百分比变化是负数还是正数。如果变化是负面的,我想把文本涂成红色,如果是正面的,我想把它涂成绿色,这就是我检查变化是正面还是负面的方式:

 // Checking whether the change is positive or negative
          
          if(item['7d'] > item['30d']) {
            this.isPositive = true
          } else if (item['7d'] < item['30d']) {
           this.isNegative = true
          }

到目前为止,我使用三元运算符的逻辑不起作用,而且我的 td 文本没有变成红色或绿色。为什么以及如何实现这一目标?这是我的全部代码:

<template>
<div>
 <v-data-table
      :headers="headers"
      :items="bitcoinInfo"
      :hide-default-footer="true"
      class="primary"
    >
      <template #item.thirtyDaysDiff="{ item }">
        <td :class="isPositive ? 'positive' : 'negative' ? isNegative : 'negative'">{{ calculateThirtyDayDifference(item) }}%</td>
      </template>
      <template #item.sevenDaysDifference="{ item }">
       <td :class="isPositive ? 'positive' : 'negative' ? isNegative : 'negative'">{{ calculateThirtyDayDifference(item) }}%</td>
      </template>
    </v-data-table>
</div>

</template>

<script>
import axios from 'axios';

  export default {
    data () {
      return {
        bitcoinInfo: [],
        isNegative: false,
        isPositive: false,
        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(item) {

         
         let calculatedPercent = 100 * Math.abs((item['7d'] - item['30d']) / ((item['7d'] + item['30d']) / 2));

          // Checking whether the change is positive or negative
          
          if(item['7d'] > item['30d']) {
            this.isPositive = true
          } else if (item['7d'] < item['30d']) {
           this.isNegative = true
          }

      return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
       },

       calculateSevenDayDifference(item) {

         let calculatedPercent = 100 * Math.abs((item['24h'] - item['7d']) / ((item['24h'] + item['7d']) / 2));
      return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
       }
      },
        
      mounted() {
        this.getBitcoinData()
      }
  }

</script>

<style>
.negative {
  color: red;
}

.positive {
  color: green;
}

</style>

你的代码有很多错误我什至不知道从哪里开始...

  1. 您使用 Conditional (ternary) operator 的方式有误。它有一个形式 condition ? expression_for_true : expression_for_false

  2. 方法calculateThirtyDayDifference在模板中使用,同时改变了一些数据(isNegativeisPositive)。 永远不要那样做!这会导致无限渲染循环。

在大多数情况下,您不需要从模板中调用任何 method - 由于模板会多次呈现,因此效率非常低。如果您有一些数据并且需要导出更多数据(计算一些东西),更好的解决方案是使用 computed 并提前准备好您需要的所有数据

  1. v-data-table (docs) 的项目插槽已经呈现 <td> 因此您的代码将在 td 内呈现 td - 例如使用 span 而不是

const data = 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}}')

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  template: `
  <v-app>
    <v-main>
      <v-container>
        <v-data-table :headers="headers" :items="rowsToDisplay" :hide-default-footer="true" class="elevation-1">
          <template #item.thirtyDaysDiff="{ item }">
            <span :class="item.thirtyDaysDiffClass">{{ item.thirtyDaysDiff }}%</span>
          </template>
          <template #item.sevenDaysDiff="{ item }">
            <span :class="item.sevenDaysDiffClass">{{ item.sevenDaysDiff }}%</span>
          </template>
        </v-data-table>
      </v-container>
    </v-main>
  </v-app>
  `,
  data() {
    return {
      bitcoinInfo: data,
      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: 'sevenDaysDiff'
        },
        {
          text: '24 Hours Ago',
          value: '24h'
        },
      ],
    }
  },
  methods: {
    calculateDifference(a, b) {
      let calculatedPercent = 100 * Math.abs((a - b) / ((a + b) / 2));
      return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
    },
    getDiffClass(a, b) {
      return a > b ? 'positive' : a < b ? 'negative' : ''
    }
  },
  computed: {
    rowsToDisplay() {
      return Object.keys(this.bitcoinInfo)
        .map(key => {
          return {
            currency: key,
            ...data[key]
          }
        }).map((item) => ({
          ...item,
          thirtyDaysDiff: this.calculateDifference(item['7d'], item['30d']),
          thirtyDaysDiffClass: this.getDiffClass(item['7d'], item['30d']),
          sevenDaysDiff: this.calculateDifference(item['24h'], item['7d']),
          sevenDaysDiffClass: this.getDiffClass(item['24h'], item['7d']),
        }))
    }
  }
})
.negative {
  color: red;
}

.positive {
  color: green;
}
<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://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

<div id="app">  
</div>