【问题标题】:vuetify: how to make v-data-table row blink when item values are updatedvuetify:如何在更新项目值时使 v-data-table 行闪烁
【发布时间】:2022-08-16 10:57:47
【问题描述】:

我想创建一个表,当项目更新时,该行会闪烁一次。

我设法在组件启动时使一行闪烁,但在更新值时它不会闪烁。

我创建了一个带有两个 css 类的示例(仅用于测试),一个闪烁一次,另一个闪烁无限。

如果我们更新项目值,我们可以看到无限仍然闪烁并随着条件的填充而改变行,但是应该闪烁一次的项目没有改变。

任何帮助将不胜感激。

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: \'#app\',
  vuetify: new Vuetify(),
  data() {
    return {
      items: [{
          id: 1,
          name: \'Frozen Yogurt\',
          calories: 159,
        },
        {
          id: 2,
          name: \'Ice cream sandwich\',
          calories: 237,
        },
        {
          id: 3,
          name: \'Eclair\',
          calories: 262,
        },
        {
          id: 4,
          name: \'Cupcake\',
          calories: 305,
        },
      ],
      headers: [{
          text: \'Dessert\',
          value: \'name\',
        },
        {
          text: \'Calories\',
          value: \'calories\'
        },
      ],
    };
  },
  methods: {
    blink(item) {
      if (item.calories > 200){
        return \'blink-great\';
      } else {
        return \'blink-less\';
      }
    },
    getRandomInt(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min)) + min;
    },
    updateValues() {
      const newValues = this.items.map((el) => { 
        return {...el, calories: this.getRandomInt(100,500)}; 
      })
      this.items = newValues
    } 
  },
  computed: {
    displayItems() {
      var newItems = this.items.map((el) => { 
        return {...el, calories: el.calories * 1}; 
      })
      return newItems
    }
  },
});
.blink-less {
  animation: blinking ease-out 1s 3;
  --background-color: #FF0000
}

.blink-great {
  animation: blinking ease-out 1s infinite;
  --background-color: #0000FF
}

@keyframes blinking {
  0% {
    background-color: var(--background-color);
  }
  100% {
    background-color: #fff;
  }
}
<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.js\"></script>
<script src=\"https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js\"></script>

<div id=\"app\">
  <v-app>
    <v-container>
      <v-row class=\"pa-5\">
        <v-btn 
          @click=\"updateValues()\"
        > Update value </v-btn>
      </v-row>
      <v-row class=\"px-5\">
        <v-data-table 
         hide-default-footer 
         :headers=\"headers\" 
         :items=\"displayItems\" 
         :item-class=\"blink\"
       />
      </v-row>
    </v-container>
  </v-app>
</div>

    标签: css vue.js vuejs2 vuetify.js css-animations


    【解决方案1】:

    我创建了一个标志并添加了新的 css 类。它可以工作,但代码很差。如果我找到了更好更干净的解决方案,我将其发布在这里

    Vue.config.productionTip = false;
    Vue.config.devtools = false;
    
    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data() {
        return {
          controlAnimation: false,
          items: [{
              id: 1,
              name: 'Frozen Yogurt',
              calories: 159,
            },
            {
              id: 2,
              name: 'Ice cream sandwich',
              calories: 237,
            },
            {
              id: 3,
              name: 'Eclair',
              calories: 262,
            },
            {
              id: 4,
              name: 'Cupcake',
              calories: 305,
            },
          ],
          headers: [{
              text: 'Dessert',
              value: 'name',
            },
            {
              text: 'Calories',
              value: 'calories'
            },
          ],
        };
      },
      
      methods: {
        blink(item) {
          if (this.controlAnimation) {
            let itemClassTrue = 'blink-even-true'
            /* check item.value, based on condition...
            itemClassTrue = 'blink-less-true'
            itemClassTrue = 'blink-even-true'
            itemClassTrue = 'blink-great-true'
            */
            return itemClassTrue;
          } else {
            let itemClassFalse = 'blink-great-false'
            /* check  item.value, based on condition...
            itemClassTrue = 'blink-less-false'
            itemClassTrue = 'blink-even-false'
            itemClassTrue = 'blink-great-false'
            */
            return itemClassFalse;
          }
        },
        getRandomInt(min, max) {
          min = Math.ceil(min);
          max = Math.floor(max);
          return Math.floor(Math.random() * (max - min)) + min;
        },
        updateValues() {
          const newValues = this.items.map((el) => { 
            return {...el, calories: this.getRandomInt(100,500)}; 
          })
          this.items = newValues
        } 
      },
      computed: {
        displayItems() {
          this.controlAnimation = !this.controlAnimation
          var newItems = this.items.map((el) => { 
            return {...el, calories: el.calories * 1}; 
          })
          return newItems
        }
      },
    });
    .blink-less-true {
      animation: blinking-less-true 1s 2 !important;
      --background-color: rgb(196, 76, 76) !important;
    }
    
    .blink-even-true {
      animation: blinking-even-true 1s 2 !important;
      --background-color: #fa0 !important;
    }
    
    .blink-great-true {
      animation: blinking-great-true 1s 2 !important;
      --background-color: rgb(3, 163, 70) !important;
    }
    
    .blink-less-false {
      animation: blinking-less-false 1s 2 !important;
      --background-color: rgb(196, 76, 76) !important;
    }
    
    .blink-even-false {
      animation: blinking-even-false 1s 2 !important;
      --background-color: #fa0 !important;
    }
    
    .blink-great-false {
      animation: blinking-great-false 1s 2 !important;
      --background-color: rgb(3, 163, 70) !important;
    }
    
    @keyframes blinking-less-false {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    
    @keyframes blinking-even-false {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    
    @keyframes blinking-great-false {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    
    @keyframes blinking-less-true {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    
    @keyframes blinking-even-true {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    @keyframes blinking-less-true {
      0% { background-color: var(--background-color); }
      100% { background-color: #fff; }
    }
    <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.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    
    <div id="app">
      <v-app>
        <v-container>
          <v-row class="pa-5">
            <v-btn 
              @click="updateValues()"
            > Update value </v-btn>
          </v-row>
          <v-row class="px-5">
            <v-data-table 
             hide-default-footer 
             :headers="headers" 
             :items="displayItems" 
             :item-class="blink"
           />
          </v-row>
        </v-container>
      </v-app>
    </div>

    【讨论】:

      【解决方案2】:

      item-class 离你不远了。它可以接受一个字符串,告诉它在项目的对象上寻找一个道具。有了这个,当您更新数据时,您可以将眨眼类添加/删除到您动态创建的道具中。

      在这种情况下,我只是将道具命名为dynamicClass

      像这样的东西: 模板:

         <v-data-table 
           hide-default-footer 
           :headers="headers" 
           :items="displayItems" 
           :item-class="dynamicClass"
         />
      

      脚本:

        methods: {
          updateRandom() {
           const randomIdx = this.generateRandomNumber(0, this.items.length - 1);
           const randomNumber = this.generateRandomNumber(1, 1200);
      
           let item = { ...this.items[randomIdx] };
           item.calories = randomNumber;
           item.dynamicClass = "blink-less";
      
           this.$set(this.items, randomIdx, item);
      
           setTimeout(() => {
             delete item.dynamicClass;
             this.$set(this.items, randomIdx, item);
           }, 2000);
         },
         generateRandomNumber(min, max) {
           return Math.floor(Math.random() * (max - min + 1) + min);
         },
       },
      

      这里的想法是我们正在从数组中的项目/对象中添加和删除类。使用this.$set() 保证反应性。但是您也可以使用Array.splice(),但无论哪种方式,您都希望替换该索引处的数据对象以保持反应性。

      这是codesandbox 中的一个工作示例

      【讨论】:

        猜你喜欢
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-21
        • 2020-02-26
        • 2019-11-10
        • 2020-12-13
        • 2019-11-19
        相关资源
        最近更新 更多