资讯专栏INFORMATION COLUMN

过渡(1):元素/组件过渡和动画

ls0609 / 899人阅读

摘要:在离开进入过渡时,受影响的其他元素应该使用移动过渡为期定义移动过渡。过渡和动画自定义过渡的类名在钩子中使用两个元素之间的过渡今日头条面试分享面试题记录记得点赞分享哦让更多的人看到这里使用了一个动画库和函数式组件。

自定义过渡的类名

另一种情况和Vue过渡执行过程见初始渲染

new Vue({
    el: "#app-2",
    data: {
        taxiCalled: false
    }
})

?

这个过程到底发生了什么?

当点击按钮时,texiCalled被设置成true,并且taxi插入页面。实际上在完成这些动作之前,Vue读取了指定的类enter-class(这里为slideInRight)并把它应用于taxi的外包元素p,然后指定类enter-active-class的情况是一样的。

enter-class在第一帧之后就被移除了,类enter-active-class也在动画结束时被移除。

这种创建动画的方式成为FLIP

First(F):动画第一帧的状态;这里既是taxi在屏幕的右边开始。

Last(L): 动画最后帧的状态;这里taxi在屏幕的最左边作为结束。

Invert(I): 使用transformopacity在第一帧和最后帧两个状态之间扭转,这里使用translateX(300px)使taxi在两个状态间产生300px的位移。

Play(p): 为我们设置的属性创建过渡,这里在2s内使taxi从右到左产生了300px的位移。

在钩子中使用Velocity
new Vue({
    el: "#app-3",
    data: {
        taxiCalled: false
    },
    methods: {
        enter(el, done) {
            Velocity(el,
                { opacity: [1, 0], translateX: ["0px", "200px"] },
                { duration: 2000, easing: "ease-out", complete: done })
        },
        leave(el, done) {
            Velocity(el,
                { opacity: [0, 1], "font-size": ["0.1em", "1em"] },
                { duration: 200, complete: done })
        }
    }
})

?

抓取enterleaveappear三种情况的时间点,每种情况上都定义了四种事件,总计12种事件(见API)。在这12种事件绑定钩子函数,这些函数可以配合CSS模式使用,也可以多带带使用。这里我们在钩子函数中使用velocity脚本动画引擎,多带带完成动画配置。

在这些钩子中不一定非要使用velocity,可以使用任何库。

上面代码中:css="false"是告诉Vue,我们关闭CSS的处理,这里可以节省点CPU时间,将跳过所有与CSS动画相关代码,单纯的使用Javascript动画。

我们这里分别在@enter@leave上绑定了钩子函数,他们将在taxi被插入和离开时执行。函数的第一个参数为外包标签(这里是

),第二个参数done必须写,尽管你可能不去用它。这是因为用Javascript代替CSS,Vue无法识别动画什么时候完成,这里Vue会认为这个离开的动画在@leave事件之前就完成了,所以执行leave没有动画渲染。

关于velocity,这种类型的API,我们称为forcefeeding,我们只要往它的实例中填写数据,不管他内部如何运行。(具体查看velocity)

初始渲染

使用appear特性,在组件第一次被插入时执行相关的转换。
使用它会给人带来一种页面很快的加载大量元素的感觉(错觉)。

这里还使用了name特性,可以使用自定义的类名("自定义过渡的类名"的相似写法),
name-enter-activename-enter等。
而使用这种自定义类名是一种好习惯。

在组件第一次插入文档时执行相关的过渡

img {
    float: left;
    padding: 5px
}
.flip-enter-active {
    transition: all 5s cubic-bezier(0.55, 0.085, 0.68, 0.53);
}
.flip-enter {
    transform: scaleY(0) translateZ(0);
    opacity: 0;
}

以上整个过程如下:
Vue发现appear特性,开始查找标签中的JavaScript钩子或指定的CSS类名。之后如果有一个name被指定,就根据这个name查到过渡的入口:mySpecifiedName-entermySpecifiedName-enter-active等。
如果以上过程失败,就会找默认的v-enterv-enter-active等。

两个元素之间的过渡
new Vue({
    el:"#app-5",
    data:{
        kisses: 0
    }
})
#app-5 button span {
    color: rgb(255, 0, 140);
}
#app-5 p {
    margin: 0;
    position: absolute;
    font-size: 3em;
}
.fade-enter-active {
    transition: opacity 5s
}
.fade-leave-active {
    transition: opacity 5s;
    opacity: 0
}
.fade-enter {
    opacity: 0
}

? frog

? princess

结果发现切换后没任何过渡效果,原因是什么呢?
原来是,Vue会启动自身的优化系统,发现两个元素一模一样,就是内容不同,因此当切换时,只做了内容的替换,标签

部分并没有被替换,因此没有过渡的效果。
我们可以为需要过渡的元素增加key属性,让Vue识别青蛙与公主两个不同的元素。如下:


    

? frog

? princess

过渡效果正常了。

最佳实践,在元素上使用key,尤其是当元素间具有不同的语义时。
多个元素之间的过渡和过渡模式

在有两个以上元素时,你可能这么做:


    

? frog

? princess

? santa

更好的方法是我们可以根据已有的数据动态的处理多元素过渡。

new Vue({
    el: "#app-6",
    data: {
        kisses: 0,
        kindOfTransformation: "fade",
        transformationMode: "in-out"
    },
    computed: {
        transformation() {
            if (this.kisses < 3) {
                return "frog"
            }
            if (this.kisses >= 3 && this.kisses <= 5) {
                return "princess"
            }
            if (this.kisses > 5) {
                this.kindOfTransformation = "zoom"
                this.transformationMode = "out-in"
                return "santa"
            }
        },
        emoji() {
            switch (this.transformation) {
                case "frog":
                    return "?"
                case "princess":
                    return "?"
                case "santa":
                    return "?"
            }
        }
    }
})

{{emoji}} {{transformation}}

以上过渡的namemode以及元素的key和内容,都将根据实例数据与计算属性进行动态的绑定。
这样做更加的灵活,并且可以为不同的元素应用不同的过渡(namemode的不同)。

这里的mode有三种情况:

不设置 旧元素离开过渡效果和新元素的进入过渡效果同时发生

in-out 新元素进入过渡先进行,完毕后旧元素的离开过渡效果再发生 如下面公主先进入,青蛙后消失

out-in 旧元素离开过渡先进行,完毕后新元素的进入过渡效果再发生 如下面公主先消失,圣诞老人后进入

再来看一个过渡模式的例子。

new Vue({
    el: "#app-7",
    data: {
        product: 0,
        products: ["?umbrella", "?computer", "?ball", "?camera"]
    }
})
#app-7 {
    margin-left:300px;
}

#app-7 p {
    position: absolute;
    margin: 0;
    font-size: 3em;
}
.slide-enter-active {
    transition: transform .5s
}
.slide-leave-active {
    transition: transform .5s;
    transform: translateX(-300px);
}
.slide-enter {
    transform: translateX(300px)
}

{{products[product % 4]}}

这似乎没什么问题。那么现在修改下CSS,去掉绝对定位。

#app-7 p {
    /* position: absolute; */
    margin: 0;
    font-size: 3em;
}

再来看看结果。

似乎是有点不对劲,为什么会这样呢?

看看过渡执行时的DOM,发现前后两个元素的过渡是同时进行,这是Vue的默认情况,即两个

同时存在,如果不使用绝对定位,那么上一个就会把下一个的位置挤掉。

这下过渡模式mode就派上用处了,我们为过渡添加mode属性为out-in,旧先出新后进。


    

{{products[product % 4]}}

列表过渡

列表过渡的情况比较复杂。一个问题一个问题看吧。

中有多个并列的元素时,我们又没有使用v-if|else指令作用其上时,会警告我们使用标签代替它。
一组列表的过渡效果,由包围,有几点比单元素过渡特殊的。

上设置tag属性外包多个元素,如

在内部以v-for把元素渲染成列表形式

每个内部的元素需要使用:key="data"标记以与它的同胞们作区分

过渡的状态不止于进入/离开,多了一个移动,使用name-move来定义类名(后面详细解释)。

看个普通示例。

new Vue({
    el: "#app-1",
    data: {
        items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
        nextNum: 10
    },
    methods: {
        ramdomIndex: function () {
            return Math.floor(Math.random() * this.items.length)
        },
        add: function () {
            this.items.splice(this.ramdomIndex(), 0, this.nextNum++)
        },
        remove: function () {
            this.items.splice(this.ramdomIndex(), 1)
        }
    }
})
.num-list-item {
    margin-right: 10px;
}
.num-list-enter,
.num-list-leave-to {
    opacity: 0;
    transform: translateY(30px);
}
.num-list-enter-active,
.num-list-leave-active {
    transition: all 2s;
}
{{item}}

很明显只有透明度的过渡,而Y轴(30px)的转换过渡没有成功,这是因为为一个inline元素,没有这种转换过渡的功能,因此我们需要把它切换成inline-block元素。

.num-list-item {
    /*把span切换成inline-block*/
    display:inline-block;
    margin-right: 10px;
}

仔细观察下还能发现个问题,其他元素因为进入/离开的那个元素,会发生位置的变化,其他元素这种移动变换没有过渡的效果,这不是我们想要的。

现在就轮到使用name-move为其他元素在此时添加移动过渡效果,很简单的做个修改:

.num-list-move,/* 为其他受到影响的元素添加移动过渡效果*/
.num-list-enter-active,
.num-list-leave-active {
    transition: all 2s;
}

观察文档结构,当进入/离开发生时,会给受影响的元素添加移动过渡类名num-list-move

进入过渡时没问题了,其他元素平滑的向右位移,但是离开过渡时其他受影响元素的移动还是没有过渡效果,这是因为定位问题,离开的元素要有2秒消失,默认的static定位要在2秒后离开元素才会腾出空位让给后面的元素,而此时此刻,移动过渡的时效2秒已经过去了,因此后面元素才会很突兀的补位。
那么,我们可以在离开状态name-leave-active上使用absolute让元素脱离正常的文档流,那么一发生离开,后面的元素就可以开始正常的移动过渡了。如下修改:

/* 在此离开过渡的状态类名添加absolute定位,以受影响元素正常的使用平滑过渡 */
.num-list-leave-active {
    position: absolute;
}

总结下,就是当使用行内元素时,使用位置转换的过渡需要把其设置为inline-block,否则位置转换没有效果。在离开/进入过渡时,受影响的其他元素应该使用移动过渡name-move为期定义移动过渡。还需要在离开过渡状态类中name-leave-active设置离开过渡元素的定位为absolute使其脱离正常的文档流,以不妨碍其他元素的移动过渡。
列表过渡的另一种写法

观察其上CSS代码,可以发现进入/离开/移动过渡定义的过渡都一样,即:

.num-list-move,
.num-list-enter-active,
.num-list-leave-active {
    transition: all 2s;
} 

因此可以去掉这些过渡状态类名,之间写在的样式里就可以了。

.num-list-item {
    display:inline-block;
    margin-right: 10px;
    /* 代替 进入/离开/移动过渡状态类 */
    transition: all 2s;
}
.num-list-enter,
.num-list-leave-to {
    opacity: 0;
    transform: translateY(30px);
}
/* 
.num-list-move,
.num-list-enter-active,
.num-list-leave-active {
    transition: all 2s;
} 
*/
/* 在此离开过渡的状态类名添加absolute定位,以受影响元素正常的使用平滑过渡 */
.num-list-leave-active {
    position: absolute;
}

其他都原封不动,效果和第一种一样。

为移动过渡添加功能

在第一种写法的基础上添加以下功能,再次理解移动过渡。
js中导入lodash库,使用shuffle方法重新排列数组items

methods: {
    ramdomIndex: function () {
        return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
        this.items.splice(this.ramdomIndex(), 0, this.nextNum++)
    },
    remove: function () {
        this.items.splice(this.ramdomIndex(), 1)
    },
    //使用`shuffle`方法重新排列数组`items`。
    shuffle: function () {
        this.items = _.shuffle(this.items)
    }
} 

页面添加一个按钮

{{item}}

列表过渡的其他示例

一个汽车站:

new Vue({
    el: "#app-2",
    data: {
        buses: [1, 2, 3, 4, 5],
        nextBus: 6
    },
    mounted() {
        setInterval(() => {
            const headOrTail = () => Math.random() >= 0.5
            if (headOrTail()) {
                this.buses.push(this.nextBus)
                this.nextBus += 1
            } else {
                this.buses.splice(0, 1)
            }
        }, 2000)
    }
})
.station-bus {
    display: inline-block;
    margin-left: 10px;
    font-size: 2em;
}
.station-enter {
    opacity: 0;
    transform: translateX(30px);
}
.station-leave-to {
    opacity: 0;
    transform: translateX(-30px);
}
.station-move,
.station-enter-active,
.station-leave-active {
    transition: all 2s;
}
.station-leave-active {
    position: absolute;
}

公交车站

? {{buses}}

在元素插入时的钩子上定义一个timer,每隔两秒一辆车进入或离开,为它们设置进入/离开过渡,和其他受影响车辆的移动过渡。

使用组件包装可重用的过渡

如果想要在我们的站点的各处重用一种过渡,把它包装进一个组件是个好方法。
要在站点上展示/隐藏一些缩略的文章,我们可以编写一个过渡组件,然后为不同的缩略文章添加这个过渡组件使其拥有过渡效果。

Vue.component("puff", {
    functional: true,
    render: function (createElement, context) {
        var data = {
            props: {
                "enter-active-class": "magictime puffIn",
                "leave-active-class": "magictime puffOut"
            }
        }
        return createElement("transition", data, context.children)
    }
})
new Vue({
    el: "#app-3",
    data: {
        showRecipe: false,
        showNews: false
    }
})

过渡和动画

自定义过渡的类名 在钩子中使用Velocity 两个元素之间的过渡 ...

今日头条

2017、2018面试分享(js面试题记录)记得点赞分享哦;让更多的人看到~~

这里使用了一个magicCSS动画库和函数式组件(todo)。
定义一个全局的函数式组件。在其render选项中定义函数并返回一个可重用的元素,在内部通过magic将进入/离开的过渡效果添加到的属性上。在页面需要的地方包裹该元素即可。

动态过渡

响应是Vue永恒的主体,因此过渡和它的属性都可以是动态的。这样我们可以控制在特定的位置与时间使用特定的过渡。

在多个元素之间的过渡和过渡模式中我们已经展示了动态过渡,对于不同的

元素,我们使用了不同的过渡效果和模式。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107642.html

相关文章

  • Vue.js进入/离开&列表过度动画

    摘要:包括以下工具在过渡和动画中自动应用可以配合第三方动画库,如在过渡钩子函数中使用直接操作可以配合使用第三方动画库,如在这里,我们只会讲到进入离开和列表的过渡。不仅可以进入和离开动画,还可以改变定位。 概述 Vue在插入、更新或则移除DOM时,提供多种不同方式的应用过渡效果。包括以下工具: *在CSS过渡和动画中自动应用class *可以配合第三方CSS动画库,如Animate.css *...

    thekingisalwaysluc 评论0 收藏0
  • 过渡(1):元素/组件过渡动画

    摘要:在离开进入过渡时,受影响的其他元素应该使用移动过渡为期定义移动过渡。过渡和动画自定义过渡的类名在钩子中使用两个元素之间的过渡今日头条面试分享面试题记录记得点赞分享哦让更多的人看到这里使用了一个动画库和函数式组件。 自定义过渡的类名 另一种情况和Vue过渡执行过程见初始渲染 new Vue({ el: #app-2, data: { taxiCalled:...

    GraphQuery 评论0 收藏0
  • vue内置组件——transition简单原理图文详解

    摘要:在元素被插入之前生效,在元素被插入之后的下一帧移除。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。版及以上定义进入过渡的结束状态。 基本概念 Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如...

    lingdududu 评论0 收藏0
  • vue内置组件——transition简单原理图文详解

    摘要:在元素被插入之前生效,在元素被插入之后的下一帧移除。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。版及以上定义进入过渡的结束状态。 基本概念 Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如...

    nihao 评论0 收藏0
  • vue内置组件——transition简单原理图文详解

    摘要:在元素被插入之前生效,在元素被插入之后的下一帧移除。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。版及以上定义进入过渡的结束状态。 基本概念 Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如...

    Alfred 评论0 收藏0

发表评论

0条评论

ls0609

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<