Code前端首页关于Code前端联系我们

用Vue3写轮播组件时,哪些功能是小白也能做但新手容易踩坑,又能让用户体验秒提的?

terry 2天前 阅读数 680 #Vue

很多刚上手Vue3的前端新手,第一次练手都会挑轮播组件——毕竟是最常见的交互模块,看起来简单无非是几张图左右滑、加个自动播放,但真写起来才发现,要么自动播放停不下来、要么切换动画生硬卡顿、要么点小圆点没反应,甚至不同浏览器表现不一样,其实不用依赖现成的UI库,自己写一个核心功能健全、体验还行的Vue3轮播,避开那几个新手高频坑,再加两个零难度加分项,整个组件就能从“能用”变“好用”。

新手轮播最容易踩的3个“致命”小坑

先别急着加花里胡哨的功能,把基础逻辑的坑填稳才是关键,不然加再多特效也白搭。

第一个坑是没有做“边界锁定+无限循环的过渡补帧”,不少新手的轮播,要么到第一张点左箭头就不动了(体验割裂),要么直接做真正的无限循环数组拼接,但切换到首尾拼接的补帧时会直接跳(比如最后一张→第一张补→第一张,跳的那一下特别明显),解决方法其实很简单,不用动数组结构,用Vue3的v-show或者v-if配合transition-group,再在首尾各加一张隐藏的补位图就行?不对,transition-group更适合列表类动画,但纯CSS transform做轮播的话,隐藏首尾补位图反而更直接——比如原始有3张图,在数组开头push第3张,在数组末尾unshift第1张,然后初始transformX是负的单图宽度(刚好显示原始第一张),当滑到补位的第3张(视觉上是原始最后一张的下一张)时,立刻把transformX切回负的单图宽度*原始数组长度的位置,且动画时间设为0,这样用户就感觉不到跳了;滑到补位的第1张同理,记得给容器加overflow: hidden,不然补位图会露出来。

第二个坑是自动播放和手动操作(箭头、小圆点、触摸滑动)的冲突处理不当,新手常犯的错误是:自动播放一直开着,哪怕用户正在点箭头或者触摸屏幕,这样会导致自动切换和手动切换“打架”,比如用户刚选到第2张,自动播放又跳到第3张了,正确的逻辑是给自动播放加一个开关,用定时器管理,初始化时打开;当用户触发任何手动操作(箭头点击事件、小圆点点击事件、触摸屏幕的touchstart事件)时,立刻清除定时器;操作完成后再重新开启定时器,重新开启的时间最好和自动播放的间隔一致,别刚停又播,给用户一点反应的时间,对了,Vue3里清除定时器一定要放在组件卸载前的onUnmounted钩子或者setup的return里的销毁函数里,不然组件销毁后定时器还在跑,会造成内存泄漏,这个虽然小但很重要,是很多大厂面试前端基础时会问的点。

第三个坑是触摸滑动的距离和方向判断太粗糙,纯CSS轮播没法直接处理移动端触摸,得加原生的touch事件:touchstart记录初始的触摸点坐标(clientX、clientY),touchmove记录实时的触摸点坐标,计算横向滑动距离deltaX和纵向滑动距离deltaY,首先要判断用户是想横向滑轮播还是纵向滑页面——如果Math.abs(deltaY) > Math.abs(deltaX),说明是纵向滑,直接return,不处理轮播的逻辑;只有当Math.abs(deltaX) > 某个阈值(比如50px,这个阈值可以根据轮播图的大小调整,太大了滑不动,太小了容易误触),才会判断方向:deltaX>0是右滑(看前一张),deltaX<0是左滑(看后一张),然后实时调整transformX的值,给用户一种“图跟着手指走”的感觉;touchend时根据方向和滑动距离判断是否切换,如果没到阈值就“回弹”到当前的图片位置,到了阈值就切换到上一张或下一张。

零难度就能加的2个秒提体验的加分项

填完坑,基础轮播已经能用了,接下来加两个不用写多少代码的加分项,整个组件的质感就上去了。

第一个加分项是“懒加载可视区域外的图片”,如果轮播图有10张甚至更多,页面加载时一下子加载所有图片会拖慢首屏速度,用户体验很差,Vue3自带了v-lazy吗?哦不对,官方没有直接提供,但可以自己写一个超级简单的自定义指令,或者直接用img标签的loading="lazy"属性——这个属性是HTML5原生的,兼容性已经非常好了,现在主流的浏览器(Chrome、Firefox、Safari、Edge的最新版本,包括国内的UC、QQ浏览器)都支持,不用自己写复杂的监听逻辑,直接在轮播图的img标签上加就行,只有当图片进入可视区域时才会加载,能大大提升首屏加载速度,如果是用背景图做轮播的话,就不能用loading="lazy"了,这时候可以自己写一个简单的监听:在data里加一个数组,记录哪些图已经加载过了,初始时只有当前显示的图设为true;当轮播切换到下一张时,把当前显示的图、上一张、下一张都设为true(提前加载相邻的图,避免切换时出现空白),然后根据这个数组决定是否显示背景图。

第二个加分项是“小圆点/数字指示器的交互反馈”,新手常犯的错误是小圆点只有点击切换的功能,没有“当前选中高亮”的反馈,或者高亮的样式特别简单,只有颜色变一下,其实可以加一点简单的动画,比如当前选中的小圆点变大、变宽,其他的小圆点缩小、变回原来的形状,或者加一个进度条,当自动播放时,进度条会慢慢变满,满了就切换到下一张——进度条的实现也很简单,用CSS的transition或者animation配合自动播放的间隔时间就行,比如自动播放的间隔是3000ms,那动画的duration就设为3000ms,timing-function设为linear,当自动播放暂停时,给进度条加一个animation-play-state: paused的样式,当自动播放重新开启时,再去掉这个样式,对了,进度条最好放在轮播图的底部或者顶部,不要挡住轮播图的内容,比如可以放在底部的小圆点下面,或者单独做一个小条放在顶部。

用Vue3写轮播组件的核心代码思路

讲完了坑和加分项,给大家理一下核心代码的思路,大家可以根据自己的需求调整:首先在setup里定义核心的数据,比如轮播图的数组imgs、当前显示的索引currentIndex、单图的宽度itemWidth(可以用ref结合onMounted钩子获取容器的宽度,再除以轮播图一次显示的数量,一般是1)、自动播放的定时器timer、是否正在触摸的标志isTouching;然后定义核心的方法,比如切换图片的方法goToIndex(接收一个索引,做边界处理和无限循环的补帧,然后更新currentIndex)、左滑的方法prev(调用goToIndex(currentIndex - 1))、右滑的方法next(调用goToIndex(currentIndex + 1))、开启自动播放的方法startAutoPlay(用setInterval调用next)、暂停自动播放的方法stopAutoPlay(清除timer)、处理touchstart的方法handleTouchStart(记录初始坐标,设置isTouching为true,暂停自动播放)、处理touchmove的方法handleTouchMove(计算deltaX和deltaY,判断是否处理轮播逻辑,实时更新transformX的值)、处理touchend的方法handleTouchEnd(判断方向和滑动距离,调用goToIndex,设置isTouching为false,重新开启自动播放);然后在模板里渲染轮播图的容器、轮播图列表、左箭头、右箭头、小圆点/数字指示器、进度条;最后在onMounted钩子中调用startAutoPlay,在onUnmounted钩子中调用stopAutoPlay。

这里要注意,用transform做轮播的话,比用left或者top做轮播性能更好,因为transform不会触发浏览器的重排(reflow),只会触发重绘(repaint)和合成(composite),这三个阶段中合成阶段的性能是最好的,所以建议大家优先用transform做轮播的切换动画,对了,还可以给轮播图的列表加一个CSS的will-change: transform属性,提前告诉浏览器这个元素要做transform动画,浏览器会提前做好优化,切换动画会更流畅。

其实用Vue3写一个好的轮播组件,不需要有多高深的技术,只要避开那几个高频坑,再加两个小的加分项,就能做出一个体验不错的组件,而且自己写轮播组件的好处是,可以完全根据自己的需求调整样式和功能,不用受现成UI库的限制,比如可以做一次显示多张图的轮播、可以做垂直方向的轮播、可以做3D效果的轮播,只要在核心代码的基础上稍微修改一下就行,大家可以自己动手试一试,练手的同时也能巩固Vue3的基础知识,比如ref、reactive、computed、watch、生命周期钩子、自定义指令、原生事件绑定等等。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门