Vue在删除DOM元素后,将行内样式转移到下一个元素[带代码段]。

问题描述 投票:0回答:1

我有问题 v-forstyles 在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>
javascript dom vuejs2
1个回答
1
投票

首先我建议你读一读Vue的内置过渡。这可能让你避免直接操作DOM。

然而,这里的主要问题是 key 属性。

当组件首次渲染时,它将创建3个 <li> 键的元素。alert-0, alert-1alert-2. 从技术上讲,它比这更复杂一些,因为涉及到VNodes,但为了解释的目的,我将坚持只说键和DOM节点。

当你删除索引1的项目时,下面的项目就会被洗牌。所以之前在索引2的项目现在在索引1。

当这个更新的数组被渲染时,它将创建2个 <li> 节点,一个有 keyalert-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 而不是它的索引。如果在你的情况下没有一个自然的选择,那么你可以使用某种形式的随机数或增量计数器来在数据中生成合适的id。

© www.soinside.com 2019 - 2024. All rights reserved.