在Vue中创建可重用的 Transition的方法

Vue.js中的transition确实很棒。毫无疑问,它们可以非常轻松地让应用程序栩栩如生,但是通常必须在每个项目中从头开始编写它们,甚至还需要引入animate.css之类的CSS库来使它们功能更强大。

如果我们可以将它们封装到组件中,并在多个项目中简单地重用它们,结果会怎样呢?我们将介绍几种定义transition的方法,并深入研究如何使它们真正可重用。

原始transition组件和CSS

定义transition的最简单方法是使用transition·或transition-group组件。这需要为transition定义一个name`和一些CSS。

<template>
 <div id="app">
 <button v-on:click="show = !show">
 Toggle
 </button>
 <transition name="fade">
 <p v-if="show">hello</p>
 </transition>
 </div>
</template>
<script>
export default {
 name: "App",
 data() {
 return {
 show: true
 };
 }
};
</script>
<style>
.fade-enter-active,
.fade-leave-active {
 transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
 opacity: 0;
}
</style> 

看起来容易,对吧?然而,这种方法有一个问题。我们不能在另一个项目中真正重用这个transition。

封装transition组件

如果我们将前面的逻辑封装到一个组件中,并将其用作一个组件,结果会怎样呢?

// FadeTransition.vue
<template>
 <transition name="fade">
 <slot></slot>
 </transition>
</template>
<script>
export default { 

};
</script>
<style>
.fade-enter-active,
.fade-leave-active {
 transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
 opacity: 0;
}
</style> 

// App.vue 

<template>
 <div id="app">
 <button v-on:click="show = !show">
 Toggle transition
 </button>
 <fade-transition>
 <div v-if="show" class="box"></div>
 </fade-transition>
 </div>
</template>
<script>...</script>
<style>...</style> 

通过在transition组件中提供一个slot,我们几乎可以像使用基本transition组件一样使用它。这比前面的例子稍微好一点,但是如果我们想要传递其他特定于transition的prop,比如mode或者一些hook,该怎么办呢

封装的包装器transition组件

幸运的是,Vue 中有一个功能,使我们可以将用户指定的所有额外props和监听器传递给我们的内部标签/组件。如果你还不知道,则可以通过$attrs访问额外传递的 props,并将它们与v-bind结合使用以将它们绑定为props。这同样适用于通过$listeners进行的事件,并通过v-on对其进行应用。

// FadeTransition.vue 

<template>
 <transition name="fade" v-bind="$attrs" v-on="$listeners">
 <slot></slot>
 </transition>
</template>
<script>
export default {};
</script>
<style>
.fade-enter-active,
.fade-leave-active {
 transition: opacity 0.3s;
}
.fade-enter,
.fade-leave-to {
 opacity: 0;
}
</style> 

// App.vue 

... 

<fade-transition mode="out-in">
 <div key="blue" v-if="show" class="box"></div>
 <div key="red" v-else class="red-box"></div>
</fade-transition> 

...

「完整事例地址:https://codesandbox.io/s/yjl1wjyoy1?from-embed

现在,我们可以传递普通transition组件可以接受的任何事件和支持,这使得我们的组件更加可重用。但为什么不更进一步,增加通过 prop 轻松定制持续时间的可能性。

显式持续时间 prop

Vue 为transition组件提供了一个duration prop,然而,它是为更复杂的动画链接而设计的,它帮助 Vue 正确地将它们链接在一起。

在我们的案例中,我们真正需要的是通过组件prop控制CSS animation/transition。我们可以通过不在CSS中指定显式的CSS动画持续时间,而是将其作为样式来实现。我们可以借助transition hook来做到这一点,该transition hook与组件生命周期 hook 非常相似,但是它们在过渡所需元素之前和之后被调用。让我们看看效果如何。

// FadeTransition.vue 

<template>
 <transition name="fade"
  enter-active-class="fadeIn"
  leave-active-class="fadeOut"
  v-bind="$attrs"
  v-on="hooks">
 <slot></slot>
 </transition>
</template>
<script>
export default {
 props: {
 duration: {
 type: Number,
 default: 300
 }
 },
 computed: {
 hooks() {
 return {
 beforeEnter: this.setDuration,
 afterEnter: this.cleanUpDuration,
 beforeLeave: this.setDuration,
 afterLeave: this.cleanUpDuration,
 ...this.$listeners
 };
 }
 },
 methods: {
 setDuration(el) {
 el.style.animationDuration = `${this.duration}ms`;
 },
 cleanUpDuration(el) {
 el.style.animationDuration = "";
 }
 }
};
</script>
<style>
@keyframes fadeIn {
 from {
 opacity: 0;
 }
 to {
 opacity: 1;
 }
}
.fadeIn {
 animation-name: fadeIn;
}
@keyframes fadeOut {
 from {
 opacity: 1;
 }
 to {
 opacity: 0;
 }
}
.fadeOut {
 animation-name: fadeOut;
}
</style> 

「完整事例地址:https://codesandbox.io/s/j4qnjvmwz9?from-embed

现在,我们可以控制实际的可见过渡时间,这使我们可重用的过渡变得灵活且易于使用。但是,如何过渡多个元素(如列表项)呢?

Transition group 支持

你想到的最直接的方法可能是创建一个新组件,比如fade-transition-group,然后将当前transition标签替换为transition-group标签,以实现 group transition。如果我们可以在相同的组件中这样做,并公开一个将切换到transition-group实现的group prop,那会怎么样呢?幸运的是,我们可以通过render函数或component和is属性来实现这一点。

// FadeTransition.vue 

<template>
 <component :is="type"
  :tag="tag"
  enter-active-class="fadeIn"
  leave-active-class="fadeOut"
  move-class="fade-move"
  v-bind="$attrs"
  v-on="hooks">
 <slot></slot>
 </component>
</template>
<script>
export default {
 props: {
 duration: {
 type: Number,
 default: 300
 },
 group: {
 type: Boolean,
 default: false
 },
 tag: {
 type: String,
 default: "div"
 }
 },
 computed: {
 type() {
 return this.group ? "transition-group" : "transition";
 },
 hooks() {
 return {
 beforeEnter: this.setDuration,
 afterEnter: this.cleanUpDuration,
 beforeLeave: this.setDuration,
 afterLeave: this.cleanUpDuration,
 leave: this.setAbsolutePosition,
 ...this.$listeners
 };
 }
 },
 methods: {
 setDuration(el) {
 el.style.animationDuration = `${this.duration}ms`;
 },
 cleanUpDuration(el) {
 el.style.animationDuration = "";
 },
 setAbsolutePosition(el) {
 if (this.group) {
 el.style.position = "absolute";
 }
 }
 }
};
</script>
<style>
@keyframes fadeIn {
 from {
 opacity: 0;
 }
 to {
 opacity: 1;
 }
}
.fadeIn {
 animation-name: fadeIn;
}
@keyframes fadeOut {
 from {
 opacity: 1;
 }
 to {
 opacity: 0;
 }
}
.fadeOut {
 animation-name: fadeOut;
}
.fade-move {
 transition: transform 0.3s ease-out;
}
</style> 

// App.vue 

... 

<div class="box-wrapper">
 <fade-transition group :duration="300">
 <div class="box"
  v-for="(item, index) in list"
  @click="remove(index)"
  :key="item"
 >
 </div>
 </fade-transition>
</div> 

... 

「完整事例地址:https://codesandbox.io/s/pk9r5j2257?from-embed

[文档中][6]介绍了一个带有transition-group元素的警告。我们基本上必须在元素离开时将每个项目的定位设置为absolute,以实现其他项目的平滑移动动画。我们也必须添加一个move-class并手动指定过渡持续时间,因为没有用于移动的 JS hook。我们将这些调整添加到我们的上一个示例中。

再做一些调整,通过在mixin中提取 JS 逻辑,我们可以将其应用于轻松创建新的transition组件,只需将其放入下一个项目中即可。

Vue Transition

在此之前描述的所有内容基本上都是这个小型 [transition 集合][7]所包含的内容。它有 10 个封装的transition组件,每个约1kb(缩小)。我认为它非常方便,可以轻松地在不同的项目中使用。你可以试一试:)

总结

我们从一个基本的过渡示例开始,并最终通过可调整的持续时间和transition-group支持来创建可重用的过渡组件。我们可以使用这些技巧根据并根据自身的需求创建自己的过渡组件。希望读者从本文中学到了一些知识,并且可以帮助你们建立功能更好的过渡组件。

到此这篇关于在Vue中创建可重用的 Transition的方法的文章就介绍到这了,更多相关vue创建Transition内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue2.0 中使用transition实现动画效果使用心得

    实践 这里将通过四个实践小案例来体验和学习css过渡,css动画,javascript钩子,列表过渡的应用.至于案例用到的知识点就请自行学习官网文档. 1.css过渡–实践 先来看看demo效果: 这个案例其实很简单,通过一个transition来触发多个子元素的过渡效果,我们只需要定义元素对应的过渡效果就可以,其他事情vue会帮我们搞定,由此可以扩展出其他酷炫的过渡场景效果.先来看看这个简单案例的代码实现: <template> <div class="app"&g

  • Vue 过渡(动画)transition组件案例详解

    Vue过度(动画),本质走的是CSS3:transtion,animation. 控制器div显示/隐藏,代码如下: <div id="box"> <input type="button" value="按钮" @click="toggle"> <div id="div1" v-show="isShow"></div> </div&g

  • Vue-router结合transition实现app前进后退动画切换效果的实例

    一丶首先配置路由并且修改路由配置 路由配置就不讲了重点,给VueRoute添加一个goBack方法,用于记录路由的前进后退状态 this.isBack = true VueRouter.prototype.goBack = function () { this.isBack = true window.history.go(-1) } 二丶监听路由变化(在路由变化时判断此时的路由状态是前进还是后退) <template> <div> 动态绑定路由动画,根据路由状态的不同绑定不同的路

  • Vue Transition实现类原生组件跳转过渡动画的示例

    最近学习了Vue Transition的用法,感觉这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记 官方文档:https://cn.vuejs.org/v2/guide/transitions.html 演示地址:http://www.coderlife.com (请在移动端查看,PC端查看请打开移动端调试模式) 前言 看了挺多Vue的UI框架都不带过渡动画,今天心血来潮,就把自己平时用的动效抽离出来.可直接通过脚手架init模版配合其他UI框架使用,不需要另外进行配置. 原理 模版中

  • 关于vue状态过渡transition不起作用的原因解决

    总所周知,vue中的transition标签可以方便得进行动画过渡,使用的方法也很简单. <transition name="你要的名字"> 过渡的元素... </transition> 这里需要主要一点的是:过渡的元素只能是以下之一: 条件渲染 (使用 v-if) 条件展示 (使用 v-show) 动态组件 组件根节点 常用的过渡名称有fade等 你可以这样用 <transition name="fade"> 过渡的元素...

  • Vue 页面切换效果之 BubbleTransition(推荐)

    CodePen 地址 前端使用 SPA 之后,能获得更多的控制权,比如页面切换动画,使用后端页面我们可能做不了上面的效果,或者做出来会出现明显的闪屏.因为所有资源都需要重新加载. 今天使用 vue,vue-router,animejs 来讲解如何上面的效果是如何实现的. 步骤 点击菜单,生成 Bubble,开始执行入场动画 页面跳转 执行退场动画 函数式调用组件 我希望效果是通过一个对象去调用,而不是 v-show, v-if 之类的指令,并且为了保持统一,仍然使用 Vue 来写组件.我通常会用

  • vue页面切换过渡transition效果

    首先得有你想要的过渡效果css代码: .vux-pop-out-enter-active, .vux-pop-out-leave-active, .vux-pop-in-enter-active, .vux-pop-in-leave-active { will-change: transform; transition: all 500ms; height: 100%; position: absolute; backface-visibility: hidden; perspective: 1

  • 在Vue中创建可重用的 Transition的方法

    Vue.js中的transition确实很棒.毫无疑问,它们可以非常轻松地让应用程序栩栩如生,但是通常必须在每个项目中从头开始编写它们,甚至还需要引入animate.css之类的CSS库来使它们功能更强大. 如果我们可以将它们封装到组件中,并在多个项目中简单地重用它们,结果会怎样呢?我们将介绍几种定义transition的方法,并深入研究如何使它们真正可重用. 原始transition组件和CSS 定义transition的最简单方法是使用transition·或transition-group

  • 如何在Vue中实现Svelte的Defer Transition

    最近观看了Rich Harris的<Rethinking Reactivity>视频,惊叹于Svelte框架的高效同时,还发现了Vue所不具备的一些关于动画的原生支持-defer transitions. 先看看Svelte所谓的defer transition的效果吧. 这是使用Svelte做的Todo Demo应用.整个todo分成3个部分.输入部分,todo列表和done列表.当点击todo列表中的条目时,相应条目会被"移动"到done列表,反之亦然. 在这里,条目从

  • 在Vue中使用highCharts绘制3d饼图的方法

    highcharts是国外知名基于javascript的图表库.由于中文官网的vue中使用highcharts配置繁琐并且需要引入jquery作为依赖,所以弃用. 接下来,给各位伙伴简要的讲叙下highcharts在vue中的使用和配置方法. 首先使用 npm在你的项目中安装vue-highcharts npm install vue-highcharts --save 由于vue-highcharts依赖于highcharts,我们还需要安装后者 npm install highcharts

  • vue中简单弹框dialog的实现方法

    效果如下,dialog中内容自行添加 <template> <div> <div class="dialog-wrap"> <div class="dialog-cover" v-if="isShow" @click="closeMyself"></div> <transition name="drop"> <div class=

  • vue中实现图片压缩 file文件的方法

    项目中遇到上传图片需要在前端进行图片压缩,将我的实现思路记录一下.(我已经拿到上传的file文件的前提下) 先创建一个公用的js,这里我的是api.js,里面封装一些常用的方法 将图片压缩的方法写到这个公用的js(api.js)中 //base64转码(压缩完成后的图片为base64编码,这个方法可以将base64编码转回file文件) function dataURLtoFile(dataurl) { var arr = dataurl.split(','), mime = arr[0].ma

  • Vue中强制组件重新渲染的正确方法

    有时候,依赖 vue 响应方式来更新数据是不够的,相反,我们需要手动重新渲染组件来更新数据.或者,我们可能只想抛开当前的DOM,重新开始.那么,如何让vue以正确的方式重新呈现组件呢? 强制 Vue 重新渲染组件的最佳方法是在组件上设置:key. 当我们需要重新渲染组件时,只需更 key 的值,Vue 就会重新渲染组件. 这是一个非常简单的解决方案. 当然,你可能会对其他方式会更感兴趣: 简单粗暴的方式:重新加载整个页面 不妥的方式:使用 v-if 较好的方法:使用Vue的内置forceUpda

  • vue中使用js-xlsx导出excel的实现方法

    目录 安装 第一种 第二种 第三种 安装 npm install --save xlsx file-saver 在组件里面引入 import FileSaver from 'file-saver' import XLSX from 'xlsx' 第一种 其中#outTable是在el-table上定义的id exportExcel() {       var xlsxParam = { raw: true };//转换成excel时,使用原始的格式       var wb = XLSX.uti

  • vue中如何动态绑定图片,vue中通过data返回图片路径的方法

    在项目中遇到需要动态加载图片路径,图片路径并非是从后台获取过来的数据. 因此在data中必须用require加载,否则会当成字符串来处理. HTML如下: JS如下: 以上这篇vue中如何动态绑定图片,vue中通过data返回图片路径的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: Vue.js中的图片引用路径的方式 基于vue 动态加载图片src的解决方法 vue cli使用绝对路径引用图片问题的解决

  • vue中动态绑定表单元素的属性方法

    在vue中有时候可能想像使用jq一样给某个元素添加属性,如 $('#select1').attr('disabled','disabled') 这种方法也能实现,但是在vue中能用vue的方法还是尽量不要使用jq 使用vue的方法来添加属性可以这样: <select v-model='issues' class="ui dropdown t-select-list" :disabled='isDisabled'> <option></option>

  • vue中v-for加载本地静态图片方法

    vue-cli 项目中本地图片放在assets目录下(原因vue-cli最开始的vue图片就在里面,就把所有图片放在里面了): 之后v-for 动态加载图片路径就遇到了问题 源码: <ul> <li v-for="(item,index) in teamInfo" @click="trastFun(item)"> <div><img v-bind:src="item.imageurl"/></

随机推荐