Vue 页面之间跳转过渡动画实现

  • Post author:
  • Post category:vue


实现效果:

1.首页-商品详情页 ,界面往左滑动;

2.商品详情页-首页,界面往右滑动;

3.同级页面跳转 不触发滑动效果;

项目地址 :

https://gitee.com/wangLi1997/vue-app

演示地址:

http://www.itdream.site/h5

感谢13大佬的项目支持:

http://47.99.134.126:5000/#/home

1.路由/route.index.js配置

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const originalPush = VueRouter.prototype.push

VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)

}

const routes = [
  {
    path: '/',
    name: 'Home',
    meta:{
      index: 1,
      title:'首页',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/Home.vue')
  },
  {
    path: '/about',
    name: 'About',
    meta:{
      index: 2,
      title:'关于',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/cate',
    name: 'Cate',
    meta:{
      index: 1,
      title:'分类',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/Cate.vue')
  },
  {
    path: '/cart',
    name: 'Cart',
    meta:{
      index: 1,
      title:'购物车',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/Cart.vue')
  },
  {
    path: '/user',
    name: 'User',
    meta:{
      index: 1,
      title:'个人中心',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/User.vue')
  },
  {
    path: '/goodsDetail',
    name: 'GoodsDetail',
    meta:{
      index: 2,
      title:'商品详情',
    },
    component: () => import(/* webpackChunkName: "about" */ '../views/GoodsDetail.vue')
  }
]

const router = new VueRouter({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})

export default router

2.App.vue 监听路由,以及相关样式

<template>
    <div id="app">
        <transition :name="transitionName">
            <router-view class="router-view" />
        </transition>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                transitionName: 'slide-left'
            }
        },
        watch: {
            //使用watch 监听$router的变化
            $route(to, from) {
                // 有主级到次级
                if (to.meta.index > from.meta.index) {
                    this.transitionName = 'slide-left' // 向左滑动
                } else if (to.meta.index < from.meta.index) {
                    // 由次级到主级
                    this.transitionName = 'slide-right'
                } else {
                    this.transitionName = ''   //同级无过渡效果
                }
            }
        }
    }
</script>

<style>
    #app {
        font-family: Avenir, Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
    }

    #nav {
        padding: 30px;
    }

    #nav a {
        font-weight: bold;
        color: #2c3e50;
    }

    #nav a.router-link-exact-active {
        color: #42b983;
    }

    .router-view{
        width: 100%;
        height: auto;
        position: absolute;
        top: 0;
        bottom: 0;
        margin: 0 auto;
        -webkit-overflow-scrolling: touch;
    }

    .slide-right-enter-active,
    .slide-right-leave-active,
    .slide-left-enter-active,
    .slide-left-leave-active{
        height: 100%;
        will-change: transform;
        transition: all 500ms;
        position: absolute;
        backface-visibility: hidden;
    }
    .slide-right-enter{
        opacity: 0;
        transform: translate3d(-100%, 0, 0);
    }
    .slide-right-leave-active{
        opacity: 0;
        transform: translate3d(100%, 0, 0);
    }
    .slide-left-enter{
        opacity: 0;
        transform: translate3d(100%, 0, 0);
    }
    .slide-left-leave-active{
        opacity: 0;
        transform: translate3d(-100%, 0, 0);
    }

    .van-badge--fixed {
        z-index: 1000;
    }

</style>

3.Home.vue

<template>
  <div >
    <Header />
    <Menu />
    <div class="home">
      <!--轮播图-->
      <div class="home-swipe">
        <van-swipe :autoplay="3000" lazy-render>
          <van-swipe-item @click="clickSwipe(image)" v-for="image in images" :key="image">
            <img :src="image" />
          </van-swipe-item>
        </van-swipe>
      </div>
      <!--模块菜单分类-->
      <div class="home-cate">
        <van-row justify="center">
          <van-col class="home-cate-col" span="6" v-for="(item,index) in homeCates" :key='index'>
            <div class="home-cate-item">
              <img :src="item.img" />
              <span>{{item.name}}</span>
            </div>
          </van-col>
        </van-row>
      </div>
      <!--新品推荐-->
      <van-row justify="center">
        <van-col span="24">
          <div class="today-new">
            <span>新品推荐</span>
          </div>
        </van-col>
      </van-row>
      <!--新品推荐list-->
      <div class="goods-wrap">
        <van-row justify="center" >
          <van-col @click="goodsDetail(item.id)" span="12" v-for="(item,index) in goods" :key='index'>
            <div class="goods-item-wrap" >
              <div>
                <img style="width:5rem" :src="item.img" />
              </div>
              <div style="margin: 5px auto;">
                <span>{{item.name}}</span>
              </div>
              <div style="margin: 5px auto;color: #1baeae;">
                <span>{{item.price}}</span>
              </div>
            </div>
          </van-col>
        </van-row>
      </div>
    </div>

  </div>
</template>

<script>
// @ is an alias to /src
import Menu from "../components/Menu";
import Header from "../components/Header";

export default {
  name: 'Home',
  components: {
    Header,
    Menu
  },
  data() {
    return {
      images : [
        'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/banner-mate40.png',
        'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/banner1.png',
        'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/banner2.png'
      ],
      homeCates : [
        {
          name:'新蜂超市',
          img:'http://s.weituibao.com/1583585285461/cs.png'
        },
        {
          name:'新蜂服饰',
          img:'http://s.weituibao.com/1583585285468/fs.png'
        },
        {
          name:'全球优购',
          img:'http://s.weituibao.com/1583585285470/qq.png'
        },
        {
          name:'新蜂生鲜',
          img:'http://s.weituibao.com/1583585285472/sx.png'
        },
        {
          name:'充值缴费',
          img:'http://s.weituibao.com/1583585285465/cz.png'
        },
        {
          name:'9.9元拼单',
          img:'http://s.weituibao.com/1583585285469/pt.png'
        },
        {
          name:'每日领券',
          img:'http://s.weituibao.com/1583585285468/juan.png'
        },
        {
          name:'省钱优选',
          img:'http://s.weituibao.com/1583585285471/sq.png'
        },
      ],
      goods : [
        {
          id:1,
          name:'HUAWEI Mate 40 Pro+ 5G 全网通 12G...',
          price:'¥ 7988',
          img:'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/mate40pro%2B.png'
        },
        {
          id:2,
          name:'华为 HUAWEI P40 冰霜银 全网通5G手机',
          price:'¥ 4299',
          img:'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/p40-silver.png'
        },
        {
          id:3,
          name:'HUAWEI Mate 30 Pro',
          price:'¥ 5399',
          img:'http://47.99.134.126:28019/goods-img/mate30p3.png'
        },
        {
          id:4,
          name:'Apple iPhone XR (A2108)',
          price:'¥ 5099',
          img:'http://47.99.134.126:28019/goods-img/23ac3107-6309-40c8-bd28-164eb1186b62.jpg'
        }

      ]
    }
  },
  methods: {
    clickSwipe(image) {
      this.$dialog.alert({
        title: '提示',
        message: '功能暂未开放',
      }).then(() => {
        // on close
      })

    },
    goodsDetail(id) {
      // this.$router.push('/goodsDetail?id=' + id);
      this.$router.push({
        name: 'GoodsDetail',
        params: {
          id: id,
        }
      })
    }
  }
}
</script>
<style lang="less" scoped>
  .home{
    padding-top: 3.5rem;
  }
  /*.van-swipe{*/
  /*  height: 12rem;*/
  /*  width: 100%;*/

  /*}*/
  .van-swipe-item img{
    height: 12rem;
    width: 100%;
  }
  .home-cate-item img{
    width: 2.1rem;
  }
  .home-cate-item span{
    display: block;
    font-size: 14px;
  }
  .van-row{
    margin: 15px auto;
  }
  .home-cate-col{
    margin: 10px auto;
  }
  .today-new{
    margin: 10px auto;
    color: #1baeae;
  }
  .goods-item-wrap{
    padding: 10px;
    border-bottom: 1px solid #dcdee0;
    border-right: 1px solid #dcdee0;
    height: 10rem;
  }

  .not-border-right{
    border-right: none;
  }
  .goods-wrap{
    padding-bottom: 60px;
    .van-col:nth-child(2n) {
      .goods-item-wrap{
        border-right:none;
      }
    }
  }

  @media screen and  (min-width: 1920px) and (max-width: 2020px){
    .van-swipe-item img{
      height: 100%;
      width: 100%;
    }
    .home-cate-item img{
      width: 4.5rem;
    }
    .van-row{
      margin: 20px auto;
    }
  }
</style>

4.GoodsDetail.vue

<template>

    <div class="goods-detail">
        <van-nav-bar
                title="商品详情"
                left-text="返回"
                right-text="分享"
                left-arrow
                @click-left="onClickLeft"
                @click-right="onClickRight"
        />

        <div class="goods-content">
            <img :src="img" alt="">
            <div class="goods-name">
                <span>{{name}}</span>
            </div>
            <div class="goods-price">
                <span>¥{{price}}</span>
            </div>
            <div class="goods-distribution-type">
                <span>{{distributionType}}</span>
            </div>
            <img :src="detailImg" alt="">
        </div>
        <!--商品操作-->
        <div class="goods-operate">
            <div class="goods-operate-item">
                <div class="goods-operate-item-icon">
                    <van-icon name="chat-o" />
                </div>
                <div class="goods-operate-item-detail">
                    <span>客服</span>
                </div>
            </div>
            <div class="goods-operate-item">
                <div class="goods-operate-item-icon">
                    <van-icon name="shopping-cart-o" />
                </div>
                <div class="goods-operate-item-detail">
                    <span>购物车</span>
                </div>
            </div>
            <div class="goods-add-buy">
                <van-button round type="warning">加入购物车</van-button>
                <van-button round type="info">立即购买</van-button>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "GoodsDetail",
        data() {
            return {
                img: 'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/mate40pro%2B.png',
                name: 'HUAWEI Mate 40 Pro+ 5G 全网通 12GB+256GB(陶瓷白) ',
                detailImg: 'https://newbee-mall.oss-cn-beijing.aliyuncs.com/images/mate40pro%2Bdetail.png',
                price:'6688',
                distributionType: '免邮费 顺丰快递'
            }
        },
        created() {


        },
        methods: {
            onClickLeft() {
                this.$router.go(-1);
            },
            onClickRight() {
                this.$toast('功能尚未开放');
            },
        },
    }
</script>

<style lang="less" scoped>
    .goods-detail{
        .van-nav-bar{
            border-bottom: 1px solid #dcdee0;
        }
        .goods-content img{
            width: 100%;
        }
        .goods-name {
            text-align: left;
            font-size: 20px;
            margin: 5px auto;
        }
        .goods-price {
            text-align: left;
            font-size: 20px;
            margin: 5px auto;
            color: red;
        }
        .goods-add-buy {
            text-align: right;
            font-size: 20px;
            margin: 5px auto;
            color: red;
        }
        .goods-distribution-type{
            text-align: left;
            font-size: 15px;
            margin: 5px auto;
            color: #969799;
        }
        .goods-operate{
            position: fixed;
            right: 0;
            bottom: 0;
            left: 0;
            display: -webkit-box;
            display: -webkit-flex;
            display: flex;
            -webkit-box-align: center;
            -webkit-align-items: center;
            align-items: center;
            height: 3.33333rem;
            background-color: #fff;
            .goods-operate-item{
                padding: 5px;
                margin: 0 5px;
                .goods-operate-item-icon{
                    font-size: 25px;
                }
                .goods-operate-item-detail{
                    font-size: 12px;
                }
            }
            .goods-operate-buy {
                padding: 5px;
                margin: 0 5px;
                .van-button--warning{
                    margin-left: .13333rem;
                    border-top-right-radius: .53333rem;
                    border-bottom-right-radius: .53333rem;
                }
                .van-button--info{
                    margin-right: .13333rem;
                    border-top-right-radius: .53333rem;
                    border-bottom-right-radius: .53333rem;
                }

            }

        }
    }

</style>

以上即可实现



版权声明:本文为SpringHASh原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。