【问题标题】:Vue: updating transition name right before triggering transition doesn't render new transitionVue:在触发转换之前更新转换名称不会呈现新的转换
【发布时间】:2021-01-15 20:54:40
【问题描述】:

我看到一些我不理解的 Vue 转换行为。举个例子会更容易解释:

给定以下组件:

<transition :name="transitionName">
    <div v-if="showMe">Hey</div>
</transition>
<button @click="transitionName='slide-left'; showMe = false">Left</button>

以下是正确的:

  • 为转换名称 .slide-left.slide-right 提供了 css 类,它们的含义与它们的名称相同。
  • transitionName的初始状态为slide-right
  • showMe的初始状态为真

我希望 div 在单击按钮时向左滑动 。但是,它向右滑动

此处提供完整的可重现性:

var demo = new Vue({
  el: '#demo',

  data: {
    showMe: true,
    transitionName: 'slide-right'
  }
});
#demo {
  display: flex;
  justify-content: center;
  flex-direction: column;
  width: 20%;
  margin: 100px auto;
  text-align: center;
}

.buttons {
  display: flex;
  justify-content: space-between;
}

.slide-right-enter-active,
.slide-left-enter-active,
.slide-right-leave-active,
.slide-left-leave-active {
  transition: all 1s ease-in-out;
}

.slide-left-enter,
.slide-left-leave-to {
  transform: translateX(-100%);
}

.slide-right-enter,
.slide-right-leave-to {
  transform: translateX(100%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <transition :name="transitionName">
    <div v-if="showMe">Hey</div>
  </transition>
  <div class="buttons">
    <button @click="transitionName='slide-left'; showMe = false">left</button>
    <button @click="transitionName='slide-right'; showMe = !showMe">right</button>
  </div>
</div>

它同时包含一个“左”和“右”按钮,但无论您点击哪一个,组件都会“向右”滑动。

我可以通过将按钮的回调更改为这样来修复它:

this.transitionName = 'slide-left';
Vue.nextTick(() => {
    this.showMe = false;
});

但我想知道为什么这里需要nextTick,以及是否有更好的方法来解决一般问题。

【问题讨论】:

    标签: vue.js vue-transitions


    【解决方案1】:

    这是因为 Vue 的更新周期。它将所有更新排队并同时“刷新”它们,因此它可以评估页面的哪些部分需要更改并仅修补这些更改。当您使用 Vue.nextTick 时,您实际上是在告诉 Vue 等到下一个更新周期再设置 this.showMe = false

    docs 解释得比我好:

    ...Vue 异步执行 DOM 更新。每当观察到数据更改时,它将打开一个队列并缓冲同一事件循环中发生的所有数据更改。如果同一个 watcher 被多次触发,它只会被推入队列一次。这种缓冲的重复数据删除对于避免不必要的计算和 DOM 操作很重要。然后,在下一个事件循环“tick”中,Vue 刷新队列并执行实际的(已经去重复的)工作......

    ...例如设置vm.someData = 'new value',组件不会立即重新渲染。当队列被刷新时,它将在下一个“滴答”中更新。大多数时候我们不需要关心这个,但是当你想做一些依赖于更新后 DOM 状态的事情时,这可能会很棘手......为了等到 Vue.js 完成更新 DOM数据更改后,您可以在数据更改后立即使用Vue.nextTick(callback)。该回调将在 DOM 更新后被调用。

    【讨论】:

    • 感谢您的回复,但它并没有真正回答我的问题。我知道 nextTick 做了什么。我不明白为什么在这种情况下需要它。我更新了问题以使其更清楚。
    • 如果您在同一个循环中设置this.showMethis.transitionName,您的转换仍将使用slide-right 作为其名称。它需要在第一个周期中设置转换名称,以便在将来任何 this.showMe 的值发生更改的周期中正确评估它
    • 为什么过渡的名称是slide-right?在同一循环中设置showMetransitionName 时,它们都将被添加到队列中并为下一个循环刷新。所以当showMe 变为false 时,transitionName 将变为slide-left
    • 在不知道 确切 Vue 内部如何工作的情况下,我不能说。我猜这只是组件状态处理转换的顺序。
    猜你喜欢
    • 2012-11-28
    • 2019-08-06
    • 1970-01-01
    • 2019-04-17
    • 2017-10-31
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    相关资源
    最近更新 更多