前言
前段时间呢实现了一个模仿移动端app的通过滑动来切换路由/tab的效果,详见vuejs实现spa页面组件滑动特效。完了之后呢就在想能不能做成一个组件的形式,改进一下,抽离出来,顺便再发布到npm上,不是美滋滋?这两天正好有时间,就把它写出来了,我给他起名叫tab-slider
,中间遇到一些坑,分享一蛤。
正文
简单介绍
正如我上一篇文章所说,如果你需要这种功能
- 即将离开的组件和将要进入的组合需要同时出现在页面中
- 用手指拖动页面可以切换路由,而不仅仅是点击链接跳转
- 结合以上两点,拖动过程中同时显示两个组件,手指离开屏幕后执行切换路由或者返回的动作
tab-slider
也许可以满足你,具体实现思路可以去看上一篇文章,这里就不讲了,来看一下效果图:
改进方面
- 相比之前每个路由组件都要写
touch
事件的蠢写法,我把touch事件写在了router-view
上,增强了代码的复用,事实上不这么改我也没法将组件抽离出来给别人用 - 支持多个tab切换,之前是只有2个,写法固定,现在可以有任意个tab切换。
踩过的坑
在我开发XiXi这个仿DiDi app项目的时,我使用的Vue版本是2.4.4,而我写tab-slider
的时候使用了最新版本的Vue 2.5.16。写完之后我遇到了一个问题,滑动完毕切换路由的时候,router-view
所对应的区域会闪一下,而通过点击router-link
切换路由则不会。
Vue2.5.16效果图:
where?哪有问题?
这里一开始我觉得可能是新老项目css样式做了部分更改,影响了浏览器的重绘或是回流,苦苦搜寻无果。后来通过chrome控制台的的performance
发现:新版本的vue多了个flushCallbacks
的activity
,耗时9ms。这是什么?继续google,没什么有用的东西,ok没关系,去Vue仓库里搜,发现他第一次写入是在14 Oct 2017,也就是Vue2.5.2发布的时候,这个版本修改了nextTick
实现机制,并关闭了一个issue,有兴趣的同学可以看看。这个issue下面呢又有人reference了这个issue,里面正好讲解了相关内容。开源社区简直棒极了!
why?问题是什么?
简单来说呢就是新版Vue对于DOM相关事件是放在macro task里,其他情况默认走micro task,而micro task要先于macro task执行。而我项目中的写法是,对拖曳的dom监听了transitionend
事件,当transition结束后进行路由切换。所以原因应该是滑动结束后(也就是transition结束),路由没有在第一时间进行跳转,所以出现了一瞬间的“白屏”,在我们看来就是闪了一下。
how?怎么解决?
- solution1: 使用低版本Vue,2.4.4及以下。
- solution2: 修改写法,直接使用
settimeout
,延迟时间与动画时间一致,而由于js的异步机制,实际延迟时间总是略大于写入的延迟时间,基本上能达到想要的效果。
这里我采用了solution2,毕竟是写出来给人用了,总要有个通用的解决方案。
另外个坑就是在发布到npm之后,引入我的包,没法正常使用,提示组件未注册,折腾了许久,参考了vant和cube-ui的组件导出方式,却一直没能成功导出正确的对象。最后发现原因在于webpack
的配置上: 需要在output
属性中添加library
以及libraryTarget
,这样才能正确导出对象。
怎么用
说了那么多废话,这组件怎么用?
- 安装:npm i -S tab-slider
- 在
main.js
中引入样式,import 'tab-slider/dist/index.css'
- 在需要的组件中注册子组件,
import TabSlider from 'tab-slider'
,也可以在main.js
中引入,并通过Vue.use()
来使之成为一个全局组件。 - 接受一个
comp
的prop,类型是数组,数组中的每一项是对象,对象中又包含了name
和component
属性。其中name属性必须和路由名字相同,(这也意味着你必须为每个路由取名),component则是对应的组件。这里要注意一下,comp中每一项的顺序需要与你的router-link顺序一一对应。 - 还接受一个
default-index
,表示默认跳转的路由,从0开始。
可以改进的地方
-
webpack
相关配置还是通过vue-cli
生成的,删除了一些不必要的东西,但还是没有做到最简。打包出来的东西也有9kb,好像有点大的过分。 - 可以把
router-link
的内容也直接做进去,毕竟tab和内容区是紧密联系的。 - 提供更多的选项(prop)给使用者。
么得了
如果对你有帮助的话点个赞点个收藏点个star提个issue都是可以的哦 仓库地址