#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, данные реактивно обновляются, мой вопрос в том, почему эти анимации сбрасываются после реактивного обновления списка массивов.