首页 > 解决方案 > 如何摆脱部分CSS动画在Vuejs中更新v-for渲染列表顺序后重新启动

问题描述

我有一个数据列表,模板将使用这个列表来绘制包含每个时间栏的块列表。

列表的顺序可以随时更新我发现每次更新列表顺序时,都会意外重启一些时间条动画。

这是模拟行为的jsFiddle,有人可以建议我摆脱它的解决方案吗?谢谢!

JsFiddle 代码

https://jsfiddle.net/tklfiddle/30z4km8f/7/

Vue 模板

<div id="app">
  <h2>TimeBars:</h2>
  <button @click="reOrder">
    Shuffle
  </button>
  <ul class="listWrapper">
    <li v-for="(item, index) in list" class="row itemTest" :id="item.id" :key="item.id">
      <div class="timeBarContainer">
        <div class="timeBar" :style="{animationDuration: item.duration+ 's'}">
        </div>
        <div class="timeBarText">
          {{item.id}}
        </div>
      </div>
    </li>
  </ul>
  {{list}}
</div>

JS

new Vue({
  el: "#app",
  data: {
    list: [
      { id: "bar1", done: false, duration: 10 },
      { id: "bar2", done: false, duration: 10 },
      { id: "bar3", done: true, duration: 10 },
      { id: "bar4", done: true, duration: 10 }
    ]
  },
  mounted(){
        console.log("DEBUG: mounted", $("body"));
    $(".listWrapper").on('DOMNodeRemoved', function(e) {
      console.log(e.target, ' was removed');
    });
  },
  methods: {
    reOrder: function(){
        this.list = shuffle(this.list);
      //this.list.pop();
      console.log("DEBUG: this.list:", JSON.stringify(this.list));
      function shuffle(array) {
          var currentIndex = array.length,  randomIndex;
          // While there remain elements to shuffle...
          while (0 !== currentIndex) {
            // Pick a remaining element...
            randomIndex = Math.floor(Math.random() * currentIndex);
            currentIndex--;
            // And swap it with the current element.
            [array[currentIndex], array[randomIndex]] = [
              array[randomIndex], array[currentIndex]];
          }

          return JSON.parse(JSON.stringify(array));
        }
      }
    }
})

SCSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
  >div{
    display: inline-block;
  }
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.timeBarContainer{
  width: 100%;
  height: 15px;
  position: relative;
}

.timeBar{
  width: 100%;
  height: 100%;
  background-color: red;
  float: right;
  animation: timeBarAnimation 0s linear normal forwards;
}
.timeBarText{
  position: absolute;
}

@keyframes timeBarAnimation {
    0% {
        width: 100%;
    }
    100% {
        width: 0;
    }
}

CodeSandBox 代码

这是另一个使用 codeSandBox 编码的示例,正​​如您所见,TimeBar 组件在洗牌后没有被卸载,但 css 动画正在重新启动,这是意外的。

https://codesandbox.io/s/great-smoke-n806b?file=/src/components/TimeBar.vue

标签: javascripthtmlcssvue.js

解决方案


我希望这可以帮助你:

在 Vuejs 中更新数组和对象

当您通过直接设置索引(例如 arr[0] = val)或修改其长度属性来修改数组时。同样,Vue.js 无法接受这些更改。始终使用 Array 实例方法或完全替换它来修改数组。Vue 提供了一个方便的方法 arr.$set(index, value),它是 arr.splice(index, 1, value) 的语法糖。


推荐阅读