Vue переносит встроенный стиль на следующий элемент после удаления элемента DOM [с фрагментом] - PullRequest
0 голосов
/ 30 апреля 2020

У меня проблемы с v-for и styles на vue, посмотрите на этот пример, у меня есть несколько ошибок предупреждений, сохраненных на data, когда пользователь нажимает на кнопку закрытия li получить некоторый стиль для перемещения карты влево, а затем я удаляю эту ошибку с помощью .filter, но если удаляемый элемент является последним, но один или раньше, стиль переносится на следующий элемент, что также приводит к его исчезновению .

Шаги для воспроизведения: - Запустить фрагмент - Удалить второе предупреждение

const app = new Vue({
    el: '#app',
    data(){
    return {
        errors: [
            'test',
            'blah, blah',
            'hey, this is an error message, be careful'
        ]
    }
  },
  methods: {
      dismiss(index) {
          const errorElement = this.$refs.errorElements[index]
          errorElement.style.height = errorElement.offsetHeight + 'px'

          errorElement.style.transition = 'margin-left .2s ease-in, height .2s ease-in .2s, padding .2s ease-in .2s'
          errorElement.style.marginLeft = '-250px'

          setTimeout(() => {
              errorElement.style.height = 0
              errorElement.style.padding = 0
          }, 200)

          setTimeout(() => {
              this.errors = this.errors.filter((error, i) => {
                  return i != index
              })
          }, 600)
          // .2s of margin-left
          // .2s of delay to height and padding
          // .2s of height and padding
      }
  } 
});
* {
  margin: 0;
  padding: 0;
  outline: 0;
  text-decoration: none;
  color: inherit;
  list-style: none;
  box-sizing: border-box;
}

html, body, #app {
  height: 100vh;
  background-color: #ccc;
  font-family: 'Roboto';
}

.alert-wrapper {
  position: fixed;
  bottom: 25px;
  left: 25px;
}

.alert-wrapper ul {
  display: flex;
  flex-direction: column;
}

.alert-wrapper ul li {
  margin-top: 15px;
  padding: 15px 25px;
  background-color: #e75147;
  color: #Fff;
  font-size: 12px;
  line-height: 140%;
  border-radius: 5px;
  position: relative;
  width: 200px;
}

.alert-wrapper ul li .close {
  position: absolute;
  top: 5px;
  right: 5px;
  font-size: 12px;
  color: #Fff;
  transition: .2s;
  cursor: pointer;
  opacity: .8;
  font-weight: bold;
}

.alert-wrapper ul li .close:hover {
  opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <div class="alert-wrapper">
      <ul>
          <li v-for="(error, index) in errors" :key="`alert-${index}`" ref="errorElements">
              <span class="close" title="Fechar mensagem" @click="dismiss(index)">x</span>
              {{ error }}
          </li>
      </ul>
  </div>
</div>

1 Ответ

1 голос
/ 30 апреля 2020

Для начала предлагаю прочитать о встроенных переходах Vue. Это может позволить вам избежать непосредственного манипулирования DOM.

Тем не менее, основная проблема здесь заключается в атрибуте key.

При первом рендеринге компонента он создаст 3 <li> элементов с ключи alert-0, alert-1 и alert-2. Технически это немного сложнее, чем это, потому что задействованы VN-узлы, но для пояснения я буду придерживаться только ключей и узлов DOM.

Когда вы удаляете элемент с индексом 1, следующий элемент перетасовывается по месту , Таким образом, элемент, который ранее был в индексе 2, теперь находится в индексе 1.

Когда этот обновленный массив будет обработан, он создаст 2 <li> узла, один с key из alert-0, а другой с alert-1. Vue затем объединит старые и новые узлы и сделает необходимые исправления для перехода от одного к другому. Здесь все идет не так. Вам нужно, чтобы Vue удалил старый узел DOM alert-1, но что касается Vue, у него все еще есть узел с именем alert-1. С точки зрения Vue это alert-2, который исчез.

Так что Vue удалит узел alert-2, а не alert-1. Затем он обновит содержимое alert-1. Новое содержимое alert-1 будет таким же, как старое содержимое alert-2. Это может заставить его выглядеть так, как будто style имеет перескочившие узлы, но это не так, это - перемещенное содержимое.

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

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