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


Posted in Javascript onJune 02, 2020

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

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

在Vue中创建可重用的 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>
在Vue中创建可重用的 Transition的方法

看起来容易,对吧?然而,这种方法有一个问题。我们不能在另一个项目中真正重用这个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>

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

通过在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> 
 
...
在Vue中创建可重用的 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>
在Vue中创建可重用的 Transition的方法

「完整事例地址: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> 
 
...
在Vue中创建可重用的 Transition的方法

「完整事例地址: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内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js获取TreeView控件选中节点的Text和Value值的方法
Nov 24 Javascript
javascript实现在某个元素上阻止鼠标右键事件的方法和实例
Aug 12 Javascript
深入理解bootstrap框架之入门准备
Oct 09 Javascript
利用jquery实现下拉框的禁用与启用
Dec 07 Javascript
在js中做数字字符串补0(js补零)
Mar 25 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
Dec 07 Javascript
Vue下拉框回显并默认选中随机问题
Sep 06 Javascript
Javascript读取上传文件内容/类型/字节数
Apr 30 Javascript
Json实现传值到后台代码实例
Jun 30 Javascript
Openlayers显示瓦片网格信息的方法
Sep 28 Javascript
关于IDEA中的.VUE文件报错 Export declarations are not supported by current JavaScript version
Oct 17 Javascript
AJAX检测用户名是否存在的方法
Mar 24 Javascript
jQuery+Ajax+js实现请求json格式数据并渲染到html页面操作示例
Jun 02 #jQuery
2020淘宝618理想生活列车自动领喵币js脚本的代码
Jun 02 #Javascript
JavaScript实现手机号码 3-4-4格式并控制新增和删除时光标的位置
Jun 02 #Javascript
2020京东618叠蛋糕js脚本(亲测好用)
Jun 02 #Javascript
vue项目在webpack2实现移动端字体自适配功能
Jun 02 #Javascript
React实现类似淘宝tab居中切换效果的示例代码
Jun 02 #Javascript
实例分析javascript中的异步
Jun 02 #Javascript
You might like
php下使用无限生命期Session的方法
2007/03/16 PHP
比file_get_contents稳定的curl_get_contents分享
2012/01/11 PHP
获取用户Ip地址通用方法与常见安全隐患(HTTP_X_FORWARDED_FOR)
2013/06/01 PHP
Drupal简体中文语言包安装教程
2014/09/27 PHP
PHP中文字符串截断无乱码解决方法
2016/10/10 PHP
一个高效的JavaScript压缩工具下载集合
2007/03/06 Javascript
jquery使用ul模拟select实现表单美化的方法
2015/08/18 Javascript
对称加密与非对称加密优缺点详解
2017/02/06 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
jQuery获取table下某一行某一列的值实现代码
2017/04/07 jQuery
JavaScript实现移动端轮播效果
2017/06/06 Javascript
javascript将list转换成树状结构的实例
2017/09/08 Javascript
express 项目分层实践详解
2018/12/10 Javascript
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
javascript浅层克隆、深度克隆对比及实例解析
2020/02/09 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
2020/08/31 Javascript
Python操作MongoDB数据库PyMongo库使用方法
2015/04/27 Python
python实现颜色空间转换程序(Tkinter)
2015/12/31 Python
python采用django框架实现支付宝即时到帐接口
2016/05/17 Python
python中web框架的自定义创建
2019/09/08 Python
python 矢量数据转栅格数据代码实例
2019/09/30 Python
使用keras实现非线性回归(两种加激活函数的方式)
2020/07/05 Python
Python如何读写CSV文件
2020/08/13 Python
Python+OpenCV图像处理——实现轮廓发现
2020/10/23 Python
台湾SHOPRO购物行家:亚洲首创影视.3C.家电.优质购物平台
2018/05/07 全球购物
全球独特生活方式产品和礼品购物网站:AHAlife
2018/09/18 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
天逸系统(武汉)有限公司Java笔试题
2015/12/29 面试题
服务员岗位职责
2014/01/29 职场文书
2015年库房管理工作总结
2015/10/14 职场文书
珍惜时间的诗歌赏析
2019/08/23 职场文书
CSS中em的正确打开方式详解
2021/04/08 HTML / CSS
PyQt5 显示超清高分辨率图片的方法
2021/04/11 Python
MySQL系列之六 用户与授权
2021/07/02 MySQL
MySQL深度分页(千万级数据量如何快速分页)
2021/07/25 MySQL
Python中非常使用的6种基本变量的操作与技巧
2022/03/22 Python