You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Vue2中mode="out-in"的Transition组件无法正常生效

解决Vue2 Transition mode="out-in"不生效的问题

我看了你的代码,问题出在你把每个步骤的内容都放在了单独的<transition>组件里,这就导致mode="out-in"没法发挥它的作用啦。

问题原因

mode="out-in"的设计逻辑是:在同一个<transition>容器内,等待当前离开的元素完全结束过渡动画后,再让新的进入元素开始动画。而你现在给每个step都套了一个独立的<transition>,切换step时,前一个transition里的元素在执行离开动画的同时,后一个transition里的元素已经开始进入动画了,两个动画并行,自然看不到out-in的先后效果。

修复方案

把所有步骤的内容都放到同一个<transition>组件内部,用v-if来控制不同步骤的显示,这样mode="out-in"就能正确触发顺序动画了。

下面是修改后的完整代码:

JavaScript部分

const app = new Vue({ 
  el: '#app', 
  data() { 
    return { 
      step: 1, 
      registration: { 
        postCode: null, 
        companyOrPrivate: null, 
        companyName: null, 
        name: null, 
        email: null, 
        phone: null, 
        street: null, 
        address: null, 
        city: null, 
        skipLicense: null, 
        state: null, 
        numtickets: 0, 
        shirtsize: 'XL' 
      } 
    } 
  }, 
  methods: { 
    prev() { this.step--; }, 
    next() { this.step++; }, 
    submit() { alert('Submit.'); } 
  } 
});

CSS部分

.fade-enter-active, .fade-leave-active { 
  transition: opacity 2s; 
} 
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { 
  opacity: 0; 
}

HTML部分

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
  <div class="container registration_form">
    <div class="row">
      <div class="col-8">
        <form>
          <!-- 所有步骤都放在同一个transition里 -->
          <transition name="fade" mode="out-in" appear>
            <div v-if="step === 1" key="step1">
              <h1>Złóż zamówienie online - minimum formalności</h1>
              <div class="row">
                <div class="col-md-6 col-12">
                  <div class="form-group">
                    <label for="postCode">Wpisz kod pocztowy</label>
                    <input class="form-control" id="postCode" aria-describedby="postCode" v-model="registration.postCode">
                  </div>
                </div>
              </div>
              <div class="row">
                <div class="col-12">
                  <div class="custom-control custom-radio">
                    <input type="radio" class="custom-control-input" id="companyControll" name="radioCompanyOrPrivate" value="firma" v-model="registration.companyOrPrivate" required>
                    <label class="custom-control-label" for="companyControll">firma</label>
                  </div>
                  <div class="custom-control custom-radio">
                    <input type="radio" class="custom-control-input" id="privateControll" name="radioCompanyOrPrivate" value="osoba prywatna" v-model="registration.companyOrPrivate" required>
                    <label class="custom-control-label" for="privateControll">osoba prywatna</label>
                  </div>
                </div>
              </div>
              <button @click.prevent="next()">Next</button>
            </div>

            <div v-if="step === 2" key="step2">
              <h1>Step Two</h1>
              <p>
                <legend for="street">Your Street:</legend>
                <input id="street" name="street" v-model="registration.street">
              </p>
              <p>
                <legend for="city">Your City:</legend>
                <input id="city" name="city" v-model="registration.city">
              </p>
              <p>
                <legend for="state">Your State:</legend>
                <input id="state" name="state" v-model="registration.state">
              </p>
              <button @click.prevent="prev()">Previous</button>
              <button @click.prevent="next()">Next</button>
            </div>

            <div v-if="step === 3" key="step3">
              <h1>Step Three</h1>
              <p>
                <legend for="numtickets">Number of Tickets:</legend>
                <input id="numtickets" name="numtickets" type="number" v-model="registration.numtickets">
              </p>
              <p>
                <legend for="shirtsize">Shirt Size:</legend>
                <select id="shirtsize" name="shirtsize" v-model="registration.shirtsize">
                  <option value="S">Small</option>
                  <option value="M">Medium</option>
                  <option value="L">Large</option>
                  <option value="XL">X-Large</option>
                </select>
              </p>
              <button @click.prevent="prev()">Previous</button>
              <button @click.prevent="submit()">Save</button>
            </div>
          </transition>
        </form>
        <br/><br/>Debug: {{registration}} {{ step }}
      </div>
    </div>
  </div>
</div>

额外提示

给每个步骤的div加上唯一的key属性是个好习惯,Vue可以更准确地识别元素的切换,避免复用组件可能带来的问题,也能让过渡动画更稳定。

内容的提问来源于stack exchange,提问作者jakub martenka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:07:21