Skip to content
On this page

仿微信翻页动画及保持滚动位置

TIP

事实上本文档与《仿今日头条翻页动画及保持滚动位置》的文档内容相似度 98%。

适用范围

目前只适用于 Vue.js 2 项目,如果要应用到 Vue.js 3 可能要有少量修改,请自行修改。

技术目标

  1. 模仿《微信》APP 页面进出场动画,即:下钻时,上级页面向左移动且渐隐,目标页面向左移动且渐显;回退时,下级页面向右移动且渐隐,目标页面向右移动且渐显。

  2. 如果 A 页面已经在历史中,而 B 页面有链接可跳转到 A 页面,此时跳转的话,必须实现回退动画而不是前进动画。

  3. 如同《微信》,已访问过的页面的滚动条位置要能够自动记忆,当前进、回退时均可自动滚动到记忆位置。

  4. 要能够自由设定某页面路由到另一某页面时,滚动到记忆位置或不滚动到记忆位置。

  5. 保持滚动条位置与 keep-alive 无关,不缓存的页面也必须支持记忆滚动条位置。

  6. 关于着陆页的特别要求:实践中,Webview 的着陆页有可能不是首页,这时路由事实上是从首页跳转到着陆页,虽然有跳转,但此时不允许出现翻页动画。

DEMO

仿微信翻页动画及保持滚动位置 - 技术演示

源码

仿微信翻页动画及保持滚动位置 - 源码

实现原理

见上方源码中 App.vue、router/index.js、store/index.js 的代码和注释,尤其是 App.vue 的 mixins 和 SCSS 文件的注释

测试办法

打开上方 DEMO 链接,测试流程见上方 DEMO 各个页面中的文字介绍。

部署方法

现在假设你已经有一个新建项目或老项目。

拷贝文件或照抄代码

  1. 仿照本项目,在你项目的 App.vue 中引入一个 mixins 和一个 SCSS 文件,你可以自由修改文件内容,因为注释很清晰。

  2. 仿照本项目,你项目的 router/index.js 中必须给所有页面加上name字段,且必须给所有 TabBar 级别页面加上meta: {isTabBar: true}

  3. 你项目的 store/index.js 中必须照抄本项目的 2 个 state 和 2 个 mutations,具体看本项目源码。

  4. 本项目的 components/NavBar.vue 实现了 Webview 自下级页面着陆后,点击回退按钮则关闭页面。你可以照抄或仿照源码。

搭建页面

  1. 非 TabBar 级页面必须使用一个且只能使用一个div.normal-container容器包裹所有非 fixed 的内容,且它必须是页面最外层<div />的直接子元素。由于 TabBar 级页面不可能有动画,所以不需要使用这个 class。

  2. 非 TabBar 级页面必须给所有 fixed 元素本身(必须是本身,不得是父元素)分别加上.fixed-container,且每个 fixed 元素的宽度必须是视口宽度,如果实在无法做到,最好先引导用户关闭 fixed 元素,或者自动关闭 fixed 元素。

  3. 本项目使用了 Vant 组件库的 NavBar、TabBar、Search 组件,你可以参考相关代码。

使用标记保持滚动位置

凡希望新页面保持滚动位置,要给params传入keepScrollY: true,例如:

js
this.$router.push({ name: 'Article', query: { id: 2 }, params: { keepScrollY: true } });

注意事项

保持滚动位置前提是页面高度保持不变

道理很显然,页面高度如果是变化的,那么滚动位置有可能是不准的,所以:要么页面内容全是静态的,要么锁定每块区块的高度,要么需要使用 keep-alive 缓存内容,否则保持滚动位置就没有意义。由于使用 keep-alive 技术很简单,本项目不再演示。

注意:App.vue 的<transition />应写在<keep-alive />的外层。

关于 z-index

页面切换和复杂的页面布局都避不开z-index层级,为使问题最简单化,请你遵守:

  • 竭力避免使用z-index。当出现意外的层级顺序时,应最优先考虑调整代码书写顺序,将 Z 轴更靠上的组件写在代码更靠下方,而不是使用z-index粗暴调整层级,因为给某个元素加z-index可能会引起层级混乱,导致一系列连锁反应,类似于“你用谎言掩盖谎言,最后得到的只能是更大的谎言”,所以,比如页面顶部固定浮动的组件,虽然位置在页面最上方,但代码要写在正常流内容的下方。

  • Vant 组件库的 Tabbar 组件的默认z-index1,请重置为auto,否则也会引起一系列麻烦。本 DEMO 已实施此修改。

与《仿今日头条...》方案的区别

  1. 微信翻页动画是新旧页面都有动画,今日头条翻页动画是只有其中一个页面有动画,今日头条的动画更省资源,卡顿概率更低。

  2. 微信动画既然涉及两个页面,那么 TabBar 级页面也必须使用div.normal-container.fixed-container,而今日头条的 TabBar 级页面永远不会有动画,所以没限制。

如何切换到《仿今日头条...》方案

替换 App.vue 中引入的 SCSS 文件即可,也就是使用《仿今日头条翻页动画及保持滚动位置》源码中的对应文件。

杨亮的前端解决方案