如何为测试禁用 vue.js 转换?

Posted

技术标签:

【中文标题】如何为测试禁用 vue.js 转换?【英文标题】:How do I disable vue.js transitions for tests? 【发布时间】:2017-12-03 06:09:03 【问题描述】:

我有一个 vue.js 组件,它使用 <transition> 元素对隐藏/显示进行动画处理。

为了加快测试,我想禁用动画。我该怎么做?

这里建议* transition: none !important :https://github.com/vuejs/vue/issues/463,但似乎没有什么不同。

我在这里创建了一个小提琴:https://jsfiddle.net/z11fe07p/2268/

运行“测试”最后输出是“3。显示应该是“无”,它是:块”。如果我将超时时间增加到 100,或者删除 <transition> 元素,我会得到“3。显示应该是“无”的预期输出,它是:无”

那么如何禁用动画以便摆脱setTimeout 调用?

编辑:

我尝试删除所有 css 样式,但仍然遇到同样的问题。因此,只需使用 <transition> 元素即可触发问题。

编辑 2:

将小提琴更新为没有样式,只有<transition> 元素。还包括对$nextTick() 的调用,以确保这不是它行为怪异的原因。

wait100的调用改为wait10,你会看到测试开始失败

https://jsfiddle.net/z11fe07p/2270/

编辑 3:

将示例代码放在这里,这样每个人都可以更轻松地玩耍:)

new Vue(
  el: '#app',
  template: `
    <span>
      <button @click="test()">Run test</button>
      <transition>
        <p v-show="show">Hello, world!</p>
      </transition>
    </span>
  `,
  data() 
    return 
      show: false,
    ;
  ,
  methods: 
    test() 
      const wait10 = _ => new Promise(resolve => setTimeout(resolve, 10));
      const wait100 = _ => new Promise(resolve => setTimeout(resolve, 100));
      const showParagraph = _ => this.show = true;
      const hideParagraph = _ => this.show = false;
      const p = document.querySelector('p');

      showParagraph();

      this.$nextTick()
        .then(wait10)
        .then(() => 
          const display = getComputedStyle(p).display;
          assertEqual(display, 'block');
        )
        .then(hideParagraph)
        .then(this.$nextTick)
        .then(wait100)
        .then(() => 
          const display = getComputedStyle(p).display;
          assertEqual(display, 'none');
        );
    
  
);

function assertEqual(a, b)  
  if (a !== b) 
    console.error('Expected "' + a + '" to equal "' + b + '"');
  
;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app"></div>

【问题讨论】:

【参考方案1】:

你可以在 Vue 上设置一个变量来表示测试,如果你正在测试,可以设置transition hooks 中止。

对于我的示例,您可以使用复选框来控制测试变量的值。第一个测试结果表示发生任何事情之前的状态,因此它与之前运行的第三个测试结果相同。除此之外,您每次都可以拨动测试开关并获得预期的结果。

我已经修改了我的代码以将fadeTransition 隔离为一个带有插槽的单独组件,但我还没有找到一种方法来消除模板中为其添加的标记。

new Vue(
  el: '#app',
  template: `
    <span>
      <input type="checkbox" v-model="Vue.testing"> Testing<br>
      <button @click="test()">Run test</button>
      <fade-transition>
        <p id="transition" v-show="show">Hello, world!</p>
      </fade-transition>
    </span>
  `,
  components: 
    fadeTransition: 
      template: `
      <transition name="fade"
        @enter="killTransition"
        @leave="killTransition"
      ><slot></slot>
      </transition>
      `,
      methods: 
        killTransition(el, done) 
          if (Vue.testing) done();
        
      
    
  ,
  data() 
    return 
      show: false,
      testing: true
    ;
  ,
  methods: 
    test() 
      const p = document.querySelector('#transition');

      let display = getComputedStyle(p).display;
      console.log('1. Display should be "none", it is:', display);

      this.show = true;
      this.$nextTick(() => 
        display = getComputedStyle(p).display;
        console.log('2. Display should be "block", it is:', display);

        this.show = false;

        this.$nextTick(() => 
          display = getComputedStyle(p).display;
          console.log('3. Display should be "none", it is:', display);
        );
      );
    
  
);
.fade-enter-active,
.fade-leave-active 
  transition: opacity .5s;


.fade-enter,
.fade-leave-to 
  opacity: 0
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app"></div>

【讨论】:

对我来说这每次都有效,这告诉我我们仍然不明白这里到底发生了什么。这就是我不想选择这个作为接受的答案的原因之一。对不起。 另外,我真的不喜欢用那些只是为了测试的东西弄脏我的模板。那么有什么方法可以从我的测试代码中添加这些道具? 更新了一些关于不同结果的说明。【参考方案2】:

我在&lt;transition-group&gt; 遇到了这个问题。我的解决方案是在测试期间使用以下代码替换它。

Vue.component('transition-group', 
    props: ['tag'],
    render(createElement) 
        return createElement(this.tag || this.$vnode.data.tag || 'span', this.$slots.default);
    ,
);

这是将&lt;transition-group&gt; 转换为&lt;slot&gt; 的镜像并带有可选的动态定义标记的最低要求。

我可能需要对&lt;transition&gt; 做同样的事情。如果是这样,它可能会更简单,因为&lt;transition&gt; 没有标签属性。

【讨论】:

【参考方案3】:

当 env 为 testing 时,我基本上将所有 transitiontransition-groups 更改为具有渲染功能的 div。

if (process.env.NODE_ENV === 'testing') 
  const div = 
    functional: true,
    render: (h,  data, children ) => h('div', data, children),
  

  Vue.component('transition', div)
  Vue.component('transition-group', div)

【讨论】:

有没有办法扭转这种局面? (我正在尝试打开和关闭转换。) 您是在测试期间尝试切换还是允许用户通过(prefers-reduced-motion) / some toggle 之类的方式进行切换?在后一种情况下,我可能会将我的过渡持续时间与全局乘数挂钩。 Like: transition-duration: calc(1s * var(--transition-multiplier)) 然后你可以用:root --transition-multiplier: 1 .no-transitions --transition-multiplier: 0 这样的类来切换它【参考方案4】:

也许不是最简单的测试方法,但对于其他场景,可以考虑使用 v-bind 绑定一个没有 CSS 转换关联的转换名称。

v-bind:name="my-var"

this.myVar = “无”

【讨论】:

请花点时间阅读help center 中的editing help。 Stack Overflow 上的格式与其他网站不同。【参考方案5】:

我的用例略有不同,但要求相同:我想禁用移动屏幕的某些过渡效果。

我的解决方案是包装成一个组件。这也适用于测试(如果设置了“禁用”,例如 process.env.NODE_ENV === 'testing')。

<template>
  <transition v-if="!disable" :name="name" :mode="mode">
    <slot></slot>
  </transition>
  <div v-else>
    <slot></slot>
  </div>
</template>

<script>
export default 
  props: 
    disable: Boolean,
    name: String,
    mode: String,
  ,
;
</script>

纯粹为了测试,我认为 Bill Criswell 的回答可能是最干净的。

【讨论】:

以上是关于如何为测试禁用 vue.js 转换?的主要内容,如果未能解决你的问题,请参考以下文章

如何为测试禁用 AWS 参数存储自动配置?

如何为 std::vector 复制或使用隐式缩小转换禁用 Visual Studio 警告 C4244

Vue.js CLI 3 - 如何为 CSS/Sass 创建供应商包?

如何为 <noscript> 标签编写自动化测试?

如何为 Vue.js 组件创建自定义样式属性

Vue.js - 如何为活动菜单链接提供动态颜色