Переход списка Vue в шахматном порядке

внешний интерфейс
Переход списка Vue в шахматном порядке

交错过渡

Это колокольчики и свистки, но это не... действительно ароматный

Основываясь на vue, вам нужно знать о vuetransitionа такжеtransition-groupПользовались и поняли.

transition

пара документации vuetranstionКомпоненты уже имеют очень подробныеанализировать.

Вот мое понимание:

transtionЭто абстрактный компонент, предоставляемый Vue, который поможет нам управлять дочерними элементами, которые он оборачивает, в нужное время.

Подходящее время:

  1. beforeEnterdom генерируется из js и просто вставляется во фрейм страницы (соответствует началу анимации на рисунке ниже)
  2. enterСледующий кадр после dom вставляется на страницу (соответствует анимации на следующем рисунке)
  3. afterEnterСледующий кадр после завершения анимации dom (соответствует концу анимации на рисунке ниже)

Здесь неоднократно упоминалось понятие фрейма, я рассказывал о нем в прошлой статье, если интересно, можете глянуть.

nuggets.capable/post/684490…

transition

transition-group

ransition-groupКомпонент группирует каждый элемент в обернутом спискеtranstionработа компонента.

html
<div id="app"  @click="num === 0 ? num++ : num = 5">
    <transition-group name="list">
        <item v-for="n in num" :key=n />
    </transition-group>
</div>
css
.list-enter {
    opacity: 0;
    transform: translateY(100%);
}
.list-enter-active {
    transition: .3s;
}
/* enter-to其实可以不用写, 没有显性写明,就是默认的opacity: 1;transform: none;  */
.list-enter-to {
    opacity: 1;
    transform: translateY(0);
}

transition-group

Затем добавьте разные задержки для каждого элемента списка.

transition-delay

css
.list-enter-active:nth-child(5n+2) {
    transition-delay: .3s;
}
.list-enter-active:nth-child(5n+3) {
    transition-delay: .5s;
}
.list-enter-active:nth-child(5n+4) {
    transition-delay: .7s;
}
.list-enter-active:nth-child(5n+5) {
    transition-delay: .9s;
}

transition-delay

Использование transition-delay с селекторами css действительно может обеспечить поэтапные переходы,

Но недостаток тоже очевиден, нужно писать много css, а модифицировать не гибко.

Затем мы используем JavaScript-хук vue для его реализации.

setTimeout

html
<div id="app"  @click="num === 0 ? num++ : num = 5">
    <!-- 这里加上 v-bind:css="false" 让vue跳过对css的检测,让我们更好控制 动画完成的时机 -->
    <transition-group 
        v-bind:css="false"
        v-on:before-enter="beforeEnter" 
        v-on:enter="enter"
        v-on:after-enter="afterEnter">

        <item v-for="(n,index) in num" :key=n :data-delay=index*100 />

    </transition-group>
</div>

При использовании только переходов JavaScript вы должны использовать обратные вызовы done при вводе и выходе. В противном случае они будут вызываться синхронно и переход завершится немедленно.

new Vue({
    el: "#app",
    data: () => ({
        num: 0
    }),
    methods: {
        //让我们在 beforeEnter enter afterEnter 钩子里,把 vue 帮我们做的事,自己做一遍:
        //添加移除 class 类名,监听 transitionend 事件。
        beforeEnter(dom) {
            dom.classList.add('list-enter', 'list-enter-active');
        },
        enter(dom,done) {
            let delay = dom.dataset.delay;
            setTimeout(function () {
                dom.classList.remove('list-enter');
                dom.classList.add('list-enter-to');
                //监听 transitionend 事件
                var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
                dom.addEventListener(transitionend, function onEnd() {
                  dom.removeEventListener(transitionend, onEnd);
                  done(); //调用done() 告诉vue动画已完成,以触发 afterEnter 钩子
                });
            }, delay)
        },
        afterEnter(dom) {
            dom.classList.remove('list-enter-to', 'list-enter-active');
        }
    }
})

setTimeout

Пока это работает хорошо, и достигается эффект ступенчатых переходов без написания большого количества css.

Оглядываясь назад, мы сделали всего 2 вещи, используя.list-enter .list-enter-toа такжеsetTimeout

Скажите браузеру помещать элемент списка в разное время, начиная сopacity 0 translateY(100%) Переход к ,opacity 1 translateY(0).

Сообщите браузеру различные состояния элемента в дополнение к имени класса,

Мы можем напрямую манипулировать dom и писать встроенные стили,

Помимо того, что имена классов CSS вообще не пишутся,

Там также может быть больше программируемости.

style

html
<div id="app" @click="num ? num++ : num=5">
        <transition-group 
            v-bind:css="false" 
            v-on:before-enter="beforeEnter" 
            v-on:enter="enter"
            v-on:after-enter="afterEnter">

            <item v-for="(n,index) in num" 
                :key=n 
                :data-delay=index*100 
                data-y="100%"
                />

        </transition-group>
    </div>
new Vue({
    el: "#app",
    data: () => ({
        num: 0
    }),
    methods: {
        beforeEnter(dom) {
            let { x = 0, y = 0, s = 1, opacity = 0 } = dom.dataset;
            dom.style.cssText = `transition: .3s;opacity: ${opacity};transform: scale(${s}) translateX(${x}) translateY(${y});`;
        },
        enter(dom,done) {
            let delay = dom.dataset.delay;
            setTimeout(function () {
                dom.style.cssText = `transition: .3s;opacity: 1;transform: scale(1) translateX(0) translateY(0);`;
                //监听 transitionend 事件
                var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
                dom.addEventListener(transitionend, function onEnd() {
                  dom.removeEventListener(transitionend, onEnd);
                  done(); //调用done() 告诉vue动画已完成,以触发 afterEnter 钩子
                });
            }, delay)
        },
        afterEnter(dom) {
            dom.style.cssText = "";
        }
    }
})

style

Ну да, но поскольку все они на js, единственным ограничением является ваша фантазия.

html
    <item v-for="(n,index) in num" 
        :key=n 
        :data-delay=index*100 
        :data-x="index%2 === 0 ? '-50%' : '50%'" 
        :data-y="getRandom()+'%'"
        :data-s="Math.random()"
    />
getRandom() {
    var rate = Math.floor(Math.random() * 90 + 10);
    return Math.random() > 0.5 ? rate : -1 * rate;
}

想象力

использованная литература

[Перевод] Советы по превращению интерактивных анимаций из «хороших» в «превосходные»

transition