vue.js - Vue.js 转换的意外行为

标签 vue.js

我正在研究“滑动切换”转换以获得类似于 jQuery 的 .slideToggle() 方法的功能。我让它工作,但需要一行才能让它工作,我不确定为什么。当我从 enter()leave() 函数中删除 var neededForSomeReason = el.offsetHeight; 时,没有动画,div 只是按扣打开和关闭。

为什么转换工作需要这条线?有没有办法在没有它的情况下进行过渡?

new Vue({
  el: '#app',
  data: {
    height: 0,
    open: false,
  },
  methods: {
    toggle() {
      this.open = !this.open;
    },
    beforeEnter: function(el) {
      el.style.height = 'auto';
      el.style.display = 'block';
      this.height = el.offsetHeight;
      el.style.height = '0px';
    },
    enter: function(el) {
      // If this line is removed the transition doesn't work.
      var removeToBreak = el.offsetHeight;
      el.style.height = this.height + 'px';
    },
    afterEnter: function(el) {
      el.style.height = 'auto';
    },
    beforeLeave: function(el) {
      el.style.height = el.offsetHeight + 'px';
    },
    leave: function(el) {
      // If this line is removed the transition doesn't work.
      var removeToBreak = el.offsetHeight;
      el.style.height = '0px';
    },
  },
})
.transition-height {
  transition: height 250ms;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/0.5.3/tailwind.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<div id="app" class="p-4 bg-grey-light min-h-screen">
  <div class="bg-white rounded-sm shadow overflow-hidden">
    <div @click.prevent="toggle" class="px-8 py-4 bg-blue text-white">
      Click to Toggle
    </div>
    <transition 
      v-on:before-enter="beforeEnter" 
      v-on:enter="enter" 
      v-on:after-enter="afterEnter" 
      v-on:before-leave="beforeLeave" 
      v-on:leave="leave"
    >
      <div v-show="open" class="transition-height">
        <div class="p-8 leading-normal text-grey-darker">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis orci vitae turpis laoreet mattis. Morbi quis viverra orci. Sed vitae tincidunt nisl. Phasellus lobortis nisi mauris, non semper neque maximus at. Integer neque enim, tristique a dui sed, ultrices eleifend dolor. Mauris non tristique leo. Ut erat quam, feugiat eget venenatis eu, euismod et tortor.
        </div>
      </div>
    </transition>
  </div>
</div>

最佳答案

这可能与浏览器批处理一组同步样式更改的方式有关。

例如:

el.style.height = '10px'
el.style.height = '20px'
el.style.height = '30px'

浏览器不会在每次样式更改后立即执行布局(出于性能原因),而是会将它们全部批处理并在稍后执行单个布局。

您可以通过访问该元素的 offsetHeight 强制浏览器执行布局。参见 What forces layout / reflow .

所以你的例子本质上是这样的:

el.style.height = 'auto'
height = el.offsetHeight  // Recalculate el height (auto)
el.style.height = '0px'
el.offsetHeight           // Recalculate el height (0px)
el.style.height = height

如果没有 el.offsetHeight 行,浏览器只会看到 auto 的计算高度值与已知的 length 值的差异。不会执行到/从 auto 的转换。

如果您使用 el.offsetHeight 强制布局,则计算出的高度值将从 0px 变为已知的 length 值,即一个有效的转换。

阅读CSS transitions spec可能会提供一些见解:

Since this specification does not define when a style change event occurs, and thus what changes to computed values are considered simultaneous, authors should be aware that changing any of the transition properties a small amount of time after making a change that might transition can result in behavior that varies between implementations, since the changes might be considered simultaneous in some implementations but not others.

关于vue.js - Vue.js 转换的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50296225/

相关文章:

javascript - 编译/运行时后的 Vue.js 动态图像路径

javascript - Vue.js + Firebase - 如何显示深度嵌套的数据库

vue.js - 为什么我的 Vue 组件需要 :key?

javascript - 为什么我的图像不能在 Vue.js 2 中加载?

javascript - VueJS 调度函数的执行顺序导致问题

laravel - 使用 VueJS 和 Laravel 的 Textarea v-model 初始值

javascript - 如何在 vue.js 中复制我的组件?

javascript - Vue stopPropagation 不起作用 - child 到 parent

javascript - 如何按字母顺序对嵌套数组进行排序而不影响外部对象数组的顺序?

javascript - 如何在 for 循环的每次迭代中将值从 HTML 标记传递到 Vue 的数据对象