Как анимировать элементы списка в Vue при его удалении - PullRequest
0 голосов
/ 13 мая 2018

У меня есть вертикальный список предметов, каждый из которых можно удалить. Я помещаю свои элементы в группу переходов и создаю для них простую непрозрачность и трансформацию переходов. Переходы на удаленных элементах работают должным образом, однако, если я удаляю элемент, который не помещен внизу, элементы под ним просто подпрыгивают и занимают свое место без какого-либо перехода. Я не могу найти способ нацелить это поведение. Все, что я хочу, это просто чтобы элементы ниже плавно скользили вверх.

Есть ли способ достичь этого эффекта с помощью css tranipipms и анимационных хуков Vue?

Вот демоверсия: https://jsfiddle.net/gcp18nq0/

Шаблон:

<div id="app">
 <div class="form">
  <label for="name">Name</label>
  <input type="text" id="name" v-model="name">
  <button @click="addPlayer">Add player</button>
 </div>
 <div class="players">
  <transition-group name="player">
   <div class="panel" v-for="player in players" :key="player.id">
    <h2>
      {{ player.name}}
      <span class="remove" @click="removePlayer(player.id)">Remove</span>
    </h2>
   </div>
  </transition-group>
 </div>
</div>

Сценарий:

  data() {
    return {
     name: "",
     players: [
       {id: 1, name: 'Player1'},
       {id: 2, name: 'Player2'},
       {id: 3, name: 'Player3'},
     ]
    }
  },
  methods: {
            addPlayer: function () {
                  //,,,,
                },
            removePlayer: function (playerId) {
                   //...
            }
         }
  });

CSS

.form {
  margin:0 auto;
  width:400px;
}
.panel {
  width: 400px;
  margin: 10px auto;
  overflow: hidden;
  border: 1px solid;
  text-align: center;
}

.remove {
  float: right;
  cursor: pointer;
  text-decoration: underline;
  font-size: 12px;
  vertical-align: bottom
}

.player-enter,
.player-leave-to
/* .fade-leave-active below version 2.1.8 */

  {
  opacity: 0;
}

.player-enter {
  transform: translateY(30%);
}

.player-leave-to {
  transform: translateX(30%);
}

.player-enter-active,
.player-leave-active {
  transition: all 1.5s;
}

.player-move {
  transition: all 1.5s;
}

Единственный работающий способ, который я нашел, был путем добавления позиции: абсолютная в состояние «player-left-active», но поскольку элемент сворачивается, он меняет свою вертикальную позицию, что не является желаемым эффектом. Я также попытался изменить высоту, но там элементы ниже все еще немного подпрыгивают после того, как высота установлена ​​в 0. Я уверен, что это может быть легко достигнуто с JQuery, но я считаю, что должен быть способ сделать это без JS.

Заранее спасибо!

p.s. Это мой первый пост здесь, так что я надеюсь, что это было объяснено достаточно четко.

1 Ответ

0 голосов
/ 13 мая 2018

Итак, я сделал несколько небольших изменений для вашей скрипки: https://jsfiddle.net/gcp18nq0/1/ и, надеюсь, это то, что вы ищете.

new Vue({
  el: "#app",
  data() {
    return {
      name: "",
      players: [{
          id: 1,
          name: 'Batman'
        },
        {
          id: 2,
          name: 'Robin'
        },
        {
          id: 3,
          name: 'Superman'
        },
        {
          id: 4,
          name: 'Spiderman'
        },
      ]
    }
  },
  methods: {
    addPlayer: function() {
      const newPlayer = {
        id: this.players.length + 1,
        name: this.name,
      };
      this.players.push(newPlayer);
    },
    deletePlayer: function(playerId) {
      let playerToRemove = this.players.find((player) => {
        return player.id === playerId;
      });

      let playerIndex = this.players.indexOf(playerToRemove);
      this.players.splice(playerIndex, 1);
    }
  }
});
.form {
  margin: 0 auto;
  width: 400px;
}

.panel {
  width: 400px;
  margin: 6px auto;
  overflow: hidden;
  border: 1px solid;
  text-align: center;
  transition: all 1s;
  display: inline-block;
}

.players {
  position: relative;
  text-align: center;
}

.remove {
  float: right;
  cursor: pointer;
  text-decoration: underline;
  font-size: 12px;
  vertical-align: bottom
}

.player-enter,
.player-leave-to {
  opacity: 0;
}

.player-enter {
  transform: translateY(30%);
}

.player-leave-to {
  transform: translateX(300%);
}

.player-leave-active {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
  <div class="form">
    <label for="name">Name</label>
    <input type="text" id="name" v-model="name">
    <button @click="addPlayer">Add player</button>
  </div>
  <div class="players">
    <transition-group name="player" tag="div">
      <div class="panel" v-for="player in players" :key="player.id">
        <h2>
          {{ player.name}}
          <span class="remove" @click="deletePlayer(player.id)">Remove</span>
        </h2>
      </div>
    </transition-group>
  </div>
</div>

Самым важным изменением стал набор display: inline-block в классе .panel. Согласно документации Vue

Одним из важных примечаний является то, что эти переходы FLIP не работают с элементы установлены на дисплей: встроенный . В качестве альтернативы вы можете использовать display: inline-block или поместить элементы в гибкий контекст.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...