javascript - VueJS 仅 JS 转换 Hook 需要 setTimeout 才能使 CSS 转换正常工作

标签 javascript css vue.js css-transitions transition

我正在为 <transition-group> 使用纯 JS 钩子(Hook)VueJS 上的元素,我很困惑 enter钩子(Hook)确实有效。根据文档,我知道我必须 call done() to avoid events being called synchronously :

When using JavaScript-only transitions, the done callbacks are required for the enter and leave hooks. Otherwise, the hooks will be called synchronously and the transition will finish immediately.

但是,即使我使用它,它似乎也阻止了 CSS 转换在进入转换 时发生。我找到的唯一解决方案是使用 window.setTimeout设置样式,我认为这是一种代码味道。这是没有超时的代码和有超时的代码之间的快速视觉比较(有超时的是预期的效果):

损坏的输入过渡(左填充和不透明度没有过渡):

Broken enter transition

所需的输入转换:

Desired effect

在下面的示例中,我使用 <transition-group> 显示一个列表并想使用 JS-hooks 以便我可以在单个列表项上创建交错填充。它似乎可以正常工作,但在 enter 中除外。过渡,填充属性上的 CSS 过渡不起作用。

new Vue({
  el: '#app',
  data: {
    items: [
      'Lorem',
      'Ipsum',
      'Dolor',
      'Sit',
      'Amet'
    ],
    toggle: false
  },
  computed: {
    filteredItems: function() {
      if (!this.toggle)
        return [];

      return this.items;
    }
  },
  methods: {
    toggleItems: function() {
      this.toggle = !this.toggle;
    },
    beforeEnter: function(el) {
      el.style.paddingLeft = '0px';
      el.style.opacity = '0';
    },
    enter: function(el, done) {
      el.style.paddingLeft = `${10 * +el.dataset.index}px`;
      el.style.opacity = '1';
      done();
    },
    beforeLeave: function(el) {
      el.style.paddingLeft = '0px';
      el.style.opacity = '0';
    }
  }
})
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

ul li {
  transition: all 500ms ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">

  <button @click="toggleItems">
    Toggle items
  </button>
  
  <transition-group
    tag="ul"
    @before-enter="beforeEnter"
    @enter="enter"
    @before-leave="beforeLeave">
    
    <li
      v-for="(item, i) in filteredItems"
      v-bind:key="i"
      v-bind:data-index="i">
      {{ item }}
    </li>
  </transition-group>
</div>

如果将所有逻辑都包装在 enter 中任意超时内的方法,然后它工作:

enter: function(el, done) {
  window.setTimeout(() => {
    el.style.paddingLeft = `${10 * +el.dataset.index}px`;
    el.style.opacity = '1';
    done();
  }, 100);
},

这就是我有点困惑的地方:enter Hook 不等待beforeEnter先完成?工作片段如下

最佳答案

@enter Hook 更改为 @after-enter 应该可以修复它

我不知道为什么 @enter Hook 对此不起作用,因为查看它应该的文档,但这至少应该摆脱超时没有黑客

new Vue({
  el: '#app',
  data: {
    items: [
      'Lorem',
      'Ipsum',
      'Dolor',
      'Sit',
      'Amet'
    ],
    toggle: false
  },
  computed: {
    filteredItems: function() {
      if (!this.toggle)
        return [];

      return this.items;
    }
  },
  methods: {
    toggleItems: function() {
      this.toggle = !this.toggle;
    },
    beforeEnter: function(el) {
      el.style.paddingLeft = '0px';
      el.style.opacity = '0';
    },
    afterEnter: function(el) {
      el.style.paddingLeft = `${10 * +el.dataset.index}px`;
      el.style.opacity = '1';
    },
    beforeLeave: function(el) {
      el.style.paddingLeft = '0px';
      el.style.opacity = '0';
    }
  }
})
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

ul li {
  transition: all 500ms ease-in-out;
}

li.v-enter-active {
  transition: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">

  <button @click="toggleItems">
    Toggle items
  </button>

  <transition-group 
    tag="ul" 
    @before-enter="beforeEnter"
    @after-enter="afterEnter" 
    @before-leave="beforeLeave">
    <li v-for="(item, i) in filteredItems" v-bind:key="i" v-bind:data-index="i">
      {{ item }}
    </li>
  </transition-group>
</div>

附带说明一下,如果您使用的是 SCSS 或 SASS,则可以用它们而不是 JavaScript 来实现此目的

关于javascript - VueJS 仅 JS 转换 Hook 需要 setTimeout 才能使 CSS 转换正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55256613/

相关文章:

css - 如何在CSS中制作像背景一样的虚线网格纸

javascript - Flot 支持区间条形图吗?

javascript - HTML/HTML5 中的 60 度 Angular 文本(脚本格式)

javascript - 向切换为显示文本的标题添加向上或向下箭头

javascript - 在井内悬停时向 Bootstrap 缩略图图像添加叠加层

node.js - 我需要安装哪些软件包才能完成 "vue build <src path> --config <config file path> --dist <dist location> --prod --lib"命令?

json - VueJS 访问 JSON 数据

javascript - 无法获取 Vue 状态的元素 (Vue.js/JS/TS)

c# - en-ZA .net 中的格式文化问题

javascript - 触发组件之间的过渡