Как избавиться от частичной анимации CSS, перезапускается после обновления порядка отображения списка v-for в Vuejs

#javascript #html #css #vue.js

Вопрос:

У меня есть список данных, и шаблон будет использовать этот список для составления списка блоков, содержащих временную шкалу для каждого.

Порядок списка может быть обновлен в любое время, и я обнаружил, что при каждом обновлении порядка списка неожиданно перезапускается анимация временной шкалы.

Вот 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, как вы можете видеть, компонент TimeBar не был отключен после перетасовки, но анимация css перезапускается, что неожиданно.

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

Комментарии:

1. Мне нравится этот вопрос. Я думаю (я действительно плохо знаю ВУ), что ВУ (иногда?) повторно визуализирует <li> элементы, и исходные элементы <li> (с оригинальной анимацией) теряются (я могу наблюдать это с помощью инструмента chrome dev -> вкладка анимация). В React я могу запоминать элементы. Есть ли что-нибудь подобное и в VUE? Я пытался решить эту проблему с помощью заказа flexbox. Это вроде как работает (анимация остается), но анимация перехода не является плавной (по крайней мере, не в chrome)… jsfiddle.net/q329zvs1/2 (пожалуйста, не обращайте внимания на document.queries lol). Я надеюсь, что кто-нибудь найдет решение.

Ответ №1:

Я надеюсь, что это может вам помочь :

Обновите массив и объект в Vuejs

При изменении массива путем прямой установки индекса (например, arr[0] = val) или изменения его свойства длины. Аналогичным образом, Vue.js не могу уловить эти изменения. Всегда изменяйте массивы, используя метод экземпляра массива или полностью заменяя его. Vue предоставляет удобный метод arr.$set(индекс, значение), который является синтаксическим сахаром для arr.splice(индекс, 1, значение).

Комментарии:

1. Я не понял вашу точку зрения, мой вопрос не о том, как реактивно обновить список, так как вы можете видеть нижнюю часть моего jsfiddle и codesanbox, данные реактивно обновляются, мой вопрос в том, почему эти анимации сбрасываются после реактивного обновления списка массивов.