Vue中實現菜單下拉、收起的動畫效果


菜單的下拉和收起動畫,看起來好像比較簡單,但是搞了半天。

最后可以使用的代碼:

        <transition
          name="default"
          v-on:enter="menuEnter"
          v-on:leave="menuLeave"
          enter-class="default-enter"
          leave-to-class="default-leave-to"
        >
          <ul v-if="hasChildren(node, index)" class="menu-l2">
            <li
              v-for="(subnode, subIndex) in node.children"
              :key="subnode.id"
              @click.prevent="handleChildNodeClick(subnode, subIndex)"
              class="node-l2"
              :class="{ 'node-l2-active' : (subIndex == activeChildNodeIndex)}"
            >{{ subnode.name }}</li>
          </ul>
        </transition>

js,這里是vue中的methods部分

    menuEnter: function(el, done) {
    //這行是關鍵
      el.offsetWidth;
      el.style.maxHeight =  this.nodes[this.activeParentNodeIndex].children.length * 4 + "rem";
      el.style.transition = "all 0.3s ease-in";
      done();
    },
    menuLeave: function(el) {
      el.offsetWidth;
      el.style.maxHeight = 0;
      el.style.transition = "all 0.3s ease-out";
    }

css:

//transitions
.default-enter-active {
    transition: all 0.3s ease-in;
}

.default-leave-active {
    transition: all 0.3s ease-out;
}

.default-enter,
.default-leave-to {
    max-height: 0;
}

說明

這里結合了js和css,其實只用js也可以,但是稍微麻煩。

只用css也可以,但是效果會稍微差一些(后面會解釋)。


這里實現下拉和收起,利用的css的transition
vue中定義了三個狀態,對應顯示,分別是(事件/css類)

  • before-enter/v-enter:動畫開始/初始狀態
  • enter/v-enter-active:動畫過程/中間狀態
  • after-enter/v-enter-to:動畫結束/結束狀態

對於隱藏(leave)也同樣

計算過度高度

這里對於顯示,利用的是max-height屬性,第一個關鍵點在於,初始狀態max-height設置為0,在中間狀態設置為下拉框的實際大小。這樣才會出現高度變化的下拉效果。

這也就是為什么使用js hook,而不是直接使用css的原因呢,因為子菜單高度無法確切知道,如果對效果不敏感,可以直接指定一個較大的max-height,但是為了效果好,還是根據菜單長度確定過度最好。

控制頁面刷新

第二個關鍵點在於 el.offsetWidth;這一句看似無用的代碼,不加的話,瀏覽器不會有動畫效果,加上以后,按照網上的說法,會強制觸發繪制。

其實在vue的官方文檔有提到

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.

但是我測試了一下,調用done()還是沒有效果,不清楚原因。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM