首页 > 其他分享 >vue之移动端的页面在返回时记住操作的位置,提供滑动动画效果

vue之移动端的页面在返回时记住操作的位置,提供滑动动画效果

时间:2024-05-20 11:30:16浏览次数:8  
标签:动画 vue obj ctpRouter leave fade active query 页面

1、在main.js中添加

import ctpRouter from '@/ares-ui-extend/CtpRouter';
Vue.use(ctpRouter, router);

2、添加相应的代码

在src的目录下添加 ares-ui-extend 的文件夹

 ares-ui-extend 文件夹的下面添加CtpRouter,CtpRouter下面为:

 ctp-router.css内容为:

/*
动画样式
*/
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

.sild-leave-active {
  transition: all 1.5s;
}
 .sild-enter-active  {
  transition: all .4s;
}

/* .sild-enter /* .fade-leave-active below version 2.1.8  {
  transform:translate3d(100%, 0, 0);
}
.sild-leave-to /* .fade-leave-active below version 2.1.8  {
  transform:translate3d(-100%, 0, 0);
} */

.sild1-leave-active  {
  transition: all .4s;
}
.sild1-enter-active {
  transition: all .4s;
}
/*
.sild1-enter /* .fade-leave-active below version 2.1.8  {
  transform:translate3d(-100%, 0, 0);
}
.sild1-leave-to /* .fade-leave-active below version 2.1.8  {
  transform:translate3d(100%, 0, 0);
}
*/

.sild-enter /* .fade-leave-active below version 2.1.8 */ {
  transform: translate3d(2rem, 0, 0);
  opacity: 0;
}
.sild-leave-to /* .fade-leave-active below version 2.1.8 */ {
  transform: translate3d(-2rem, 0, 0);
  opacity: 0;
}

.sild1-enter /* .fade-leave-active below version 2.1.8 */ {
  /* transform: translate3d(-2rem, 0, 0); */
  opacity: 0;
}
.sild1-leave-to /* .fade-leave-active below version 2.1.8 */ {
  transform: translate3d(2rem, 0, 0);
  opacity: 0;
}

index.js 的内容为:

/*
拦截重写vue路由,提供滑动动画效果,记录页面位置
*/
import Nav from './nav';
import './ctp-router.css';

function CtpRouter(Vue) {
  Vue.prototype.$ctpRouter = {
    tn: 'slide', // 动画名
    keepAlives: [], // keepAlive存储
  };

  this.stack = [];
  this.PAGEKEY = new Date().getTime();

  this.createPageKey = () => {
    this.PAGEKEY += 1;
    return this.PAGEKEY.toString();
  };

  this.findStackIndex = pageKey => this.stack.findIndex(item => item === pageKey);

  this.pushStack = (pageKey) => {
    const index = this.findStackIndex(pageKey);
    this.stack.slice(0, index + 1);
    this.stack.push(pageKey);
  };

  this.clearStack = (pageKey) => {
    if (pageKey) {
      for (let i = 0; i < this.stack.length; i += 1) {
        if (pageKey === this.stack[i]) {
          this.stack.splice(i, 1);
          break;
        }
      }
    } else {
      this.stack = [];
    }
  };

  this.rewriteRouter = (router) => {
    ['push', 'replace'].forEach((method) => {
      const func = router[method].bind(router);
      router[method] = (location, onComplete, onAbort) => {
        const obj = {};
        if (typeof location !== 'object') {
          obj.path = location;
        } else {
          Object.assign(obj, location);
        }
        if (!obj.query) {
          obj.query = {};
        }
        if (method === 'push') {
          obj.query.$page_key = this.createPageKey();
          this.pushStack(obj.query.$page_key);
        }
        if (method === 'replace') {
          obj.query.$replace = true;
        }
        func(obj, onComplete, onAbort);
      };
    });
  };

  this.setKeepAlive = (router) => {
    const routes = router.options.routes;
    if (routes && routes.length > 0) {
      routes.forEach((route) => {
        const meta = route.meta;
        if (meta && meta.keepAlive) {
          Vue.prototype.$ctpRouter.keepAlives.push(route.name);
        }
      });
    }
  };

  this.setTransition = (from, to) => {
    const fromIndex = this.findStackIndex(from.query.$page_key);
    const toIndex = this.findStackIndex(to.query.$page_key);
    if (fromIndex < toIndex) { // enter
      Vue.prototype.$ctpRouter.tn = 'sild';
    } else if (fromIndex > toIndex) { // leave
      Vue.prototype.$ctpRouter.tn = 'sild1';
    } else {
      Vue.prototype.$ctpRouter.tn = 'none'; // replace则不做任何动画
    }
  };

  this.storeFromScrollTop = (vm, from) => {
    const scrollContainer = vm.$refs.scrollContainer;
    if (scrollContainer && from.meta) {
      from.meta.scrollTop = scrollContainer.scrollTop;
    }
  };

  // 跳转时,设置to页面的已记录的高度(来自于storeFromScrollTop)
  this.reStoreToScrollTop = (vm, to) => {
    const scrollContainer = vm.$refs.scrollContainer;
    if (scrollContainer && to.meta && to.meta.scrollTop) {
      scrollContainer.scrollTop = to.meta.scrollTop;
    }
  };
}
export default (Vue, router) => {
  const ctpRouter = new CtpRouter(Vue);
  ctpRouter.setKeepAlive(router);
  ctpRouter.rewriteRouter(router);

  Vue.component(Nav.name, Nav);

  Vue.mixin({
    beforeRouteEnter(to, from, next) {
      if (!to.query.$page_key) { // 首次进入的时候没有$page_key
        const obj = Object.assign({}, to);
        obj.replace = true;
        obj.query.$page_key = ctpRouter.createPageKey();
        ctpRouter.pushStack(obj.query.$page_key);
        next(obj);
      } else {
        next((vm) => {
          ctpRouter.reStoreToScrollTop(vm, to);
        });
      }
    },
    beforeRouteLeave(to, from, next) {
      if (to.query.$replace) {
        to.query.$page_key = from.query.$page_key;
        delete to.query.$replace;
        const obj = Object.assign({}, to);
        obj.replace = true;
        next(obj);
        return;
      }
      ctpRouter.storeFromScrollTop(this, from); // 记录离开时的位置
      ctpRouter.setTransition(from, to); // 设置动画
      next();
    },
  });
};

nav.vue的内容为:

<template>
  <transition :name="$ctpRouter.tn">
    <keep-alive :include="$ctpRouter.keepAlives">
      <slot></slot>
    </keep-alive>
  </transition>
</template>

<script>
export default {
  name: 'ctp-router',
};
</script>

3、用法:在定义路由的时候在meta中添加 keepAlive 的布尔值,为true则启用缓存记录页面位置,为false则不启用缓存。例子:

{
    path: '/Home/notice/notice_center',
    name: 'notice_center',
    component: resolve => require(['@/pages/Home/notice/notice_center.vue'], resolve),
    meta: {
        moduleName: 'notice_center',
        title: '消息中心', keepAlive: false   
    },
    routerLevel: 2,
}

4、总结:

ares-ui-extend 和 CtpRouter 这俩文件夹的名字,自己可以随便更改,ares-ui是公司自有的框架,所以最好是起一个别的名字。其他代码可以参考着拿来直接用。

目的就是缓存组件数据,返回上一页的时候,记录之前的操作位置,这样统一封装之后,移动端的项目有这样的需求,就直接改变路由里面meta的keepAlive值即可。

标签:动画,vue,obj,ctpRouter,leave,fade,active,query,页面
From: https://www.cnblogs.com/smile-fanyin/p/18201529

相关文章

  • 阿里云 nginx 部署vue项目的代码
    在开发完成之后需要部署我们的网站项目,那么步骤如下:打包vue项目,使用npmrunbuild将vue项目打包成dist的文件夹下面,然后将dist文件夹压缩方便上传到服务器将dist.zip上传到阿里云的文件夹下面,默认情况是上传到/var/www下面,在不配置nginx的情况下,默认情况下的放项目的地方将上......
  • 基于 Spring Boot3、Vue3!这套小说系统开源了...
    大家好,我是Java陈序员。今天,给大家介绍一个基于SpringBoot3、Vue3前后端分离的小说项目,集成了主流的技术栈,可供学习使用!关注微信公众号:【Java陈序员】,获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。项目介绍novel——一套基于SpringBoot3+Vue3开发......
  • 终于搞懂了!原来 Vue 3 的 generate 是这样生成 render 函数的
    前言在之前的面试官:来说说vue3是怎么处理内置的v-for、v-model等指令?文章中讲了transform阶段处理完v-for、v-model等指令后,会生成一棵javascriptAST抽象语法树。这篇文章我们来接着讲generate阶段是如何根据这棵javascriptAST抽象语法树生成render函数字符串的,本文中使用的v......
  • 一个页面从输入URL到加载显示完成,这个过程发生了什么?
    目录一、解析URL1、流程2、URL格式:3、示例二、浏览器封装HTTP请求报文1、流程2、HTTP请求报文例子3、封装三、DNS解析1、缓存判断1.1、浏览器缓存1.2、操作系统缓存1.3、路由器缓存2、递归查询至ISPDNS服务器3、迭代查询过程4、保存结果至各级缓存四、建立TCP连接(三次握手)1、三次......
  • 『手撕Vue-CLI』添加自定义指令
    前言经上篇『手撕Vue-CLI』添加帮助和版本号的介绍之后,已经可以在控制台中输入nue--help来查看帮助信息了,但是在帮助信息中只有--version,--help这两个指令,而vue-cli中还有很多指令,例如create,serve,build等等,所以本章将继续添加自定义指令,例如create指令。添加create......
  • Vue3使用vue3-puzzle-vcode进行滑动验证
    npm包地址:https://www.npmjs.com/package/vue3-puzzle-vcodenpm安装npminstallvue3-puzzle-vcode--save最简单例子:<template><Vcode:show="isShow"@success="onSuccess"@close="onClose"/><button@click="on......
  • Vue3+Yup进行数据验证
    Vue3+Yup进行数据验证npm安装:npmiyup使用import*asYupfrom"yup";//配置constlogin=Yup.object().shape({//username为string格式,必填(错误提示为:请输入用户名)username:Yup.string().required('请输入用户名').label("username"),password:Yup.s......
  • Vue3+nanoid编写字符串ID生成器
    Vue3+nanoid编写字符串ID生成器中文介绍:https://github.com/ai/nanoid/blob/HEAD/README.zh-CN.md一个小巧、安全、URL友好、唯一的JavaScript字符串ID生成器。“一个惊人的无意义的完美主义水平,这简直让人无法不敬佩。”小巧. 116字节(经过压缩和Brotli处理)。没有依......
  • Vue3+sweetalert2消息提示类
    为了快速编写信息提示代码,封装如下core\helper中增加swalMessage.ts,代码如下代码importSwalfrom"sweetalert2"declareinterfaceSwalMessage{success(title:string,msg:string);error(title:string,msg:string);info(title:string,msg:string);ques......
  • Vue3使用vue-cropper截图上传
    !!!!!!!已使用另一个截图上传工具,稍后更新博客!!!!!!使用vue-cropper进行截图上传先安装npmivue-cropper编写组件在components中添加imageCropper.vue代码如下<template><div><div><imgv-if="value"class="mb-2"style=&......