Vue頁面跳轉動畫效果實現

前言

現現在移動端APP對用戶體驗方面的要求愈來愈高了,最近致力於用戶體驗優化,由於須要實現相似APP頁面切換的動畫效果,百度google搜索資料不是很全,因此本身寫文檔,在實現效果的基礎上,順便惡補一波VueRouter及CSS過渡動畫的知識點,歡迎有興趣的朋友多多指教。vue

簡單demo圖預覽

寫在前面的思考

  • 如何匹配到相應須要跳轉的頁面?
  • 如何判斷是「前進」仍是「後退」然後使用不一樣的動畫方式?
  • 如何對不一樣的跳轉設置動畫效果?

實現過程

1、vue路由匹配

建立vue實例,匹配路由。
用Vue.js + Vue Router建立單頁應用,是很是簡單的。使用Vue.js,咱們能夠經過組合組件來組成應用程序,將Vue Router 添加進來以後,咱們須要作的是,將組件(components)映射到路由(routes),而後告訴Vue Router 在哪裏渲染它們。git

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
//若是使用模塊化機制編程,導入Vue和VueRouter,就須要調用Vue.use(Router)
複製代碼

接下來就能夠進行路由組件的映射:
(路由)組件的定義能夠自行定義,固然,爲了踐行模塊化組件化思想,可能是從其餘文件import進來。如下以簡單的「登陸->主頁->點單->結算」四個頁面的交互爲例:github

import Login from '@/components/login' 
import Index from '@/components/index' 
import PointList from '@/components/pointList/pointList' 
import SettLement from '@/components/pointList/settlement' 

//建立router實例,而後傳入‘routes’配置
export default new Router({
  //routes配置能夠直接傳入,也能夠先定義後使用
  //每一個路由都應該映射一個組件,其中component能夠是經過Vue.extend()建立的組件構造器,
  或者只是一個組件配飾對象。(今天暫時不考慮嵌套路由的狀況)
  routes: [
    {
      path: '/', // 登陸
      name: 'Login',
      component: Login
    },
    {
      path: '/index', // 主頁
      name: 'Index',
      component: Index
    },
    {
      path: '/pointList', // 點單
      name: 'PointList',
      component: PointList
    },
    {
      path: '/settLement', // 結算
      name: 'SettLement',
      component: SettLement
    }
]
})
複製代碼

2、路由跳轉 $router

組件路由除了使用全局組件 router-link 來實現點擊跳轉(至關於按鈕)外,還可使用組件自己
具備的一個實例對象$router及其一些屬性來達到目標。  
$router 是VueRouter的一個實例對象,至關於一個全局的路由器對象。在Vue實例內部,你能夠
經過$router訪問路由實例,裏面含有不少屬性和子對象,例如history對象,常常用到的跳轉鏈
接就能夠調用this.$router.push,this.$router.push會往history棧中添加一個新記錄。
複製代碼
聲明式 編程式
<router-link :to="..." router.push(...)

點擊 等同於調用 router.push(...)
(...)該方法的參數能夠是一個字符串,或者一個描述地址的對象:vue-router

// 字符串
router.push('home')
// 對象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
複製代碼

組件路由跳轉實例:
1.編程

<router-link :to="{name:'PointList', params: { userId: 123 }}">
      <i class="icon"><img src="../assets/point.png" alt=""></i>
      <span>點單</span>
</router-link>
複製代碼
<footer class="version" @click="goPage('Author')">v 1.0</footer>
//Js:
methods: {
    goPage(url, param) {
      this.$router.push({ name: url });
    }
}
複製代碼

3、vue路由對象$route(只讀)

在使用了vue-router的應用中,路由對象會被注入每一個組件中,賦值爲this.$route,而且當路由切換時,路由對象會被更新。因此route至關於當前正在跳轉的路由對象,能夠從裏面獲取name,path,params,query等,即包含了當前URL解析獲得的信息,還有URL匹配到的路由記錄。
路由對象暴露了如下屬性(常見):數組

  1. $route.path
字符串(string)。等於當前路由對象的路徑,會被解析爲絕對路徑,
如:http://example.com/#/login?name=aa,this.$route.path
,輸出「/login」,即對應上面1中路由匹配時routes配置中的「path」;
複製代碼
  1. $route.name
    字符串(string)。有時候,經過一個名稱來標識一個路由顯得更加方便,特別是在連接一個路由,或者是執行一些跳轉的時候。一樣,這裏的name也對應了routes配置中給某個路由設置名稱的name值:
    要連接到一個命名路由,能夠給router-link的to屬性傳一個對象:
<router-link :to="{name:'Order', params: { userId: 123 }}">
</router-link>
複製代碼

用在調用router.push()中也是一回事:瀏覽器

this.$router.push({ name: 'Order', params: { userId: 123 }})
複製代碼
  1. $route.params
    對象(object)。路由跳轉攜帶參數:
this.$router.push({ name: 'Order', params: { userId: 123 }})
console.log(this.$route.params.userId); //123
複製代碼
  1. $route.query
    對象(object)。可訪問攜帶的查詢參數:
this.$router.push({name: 'login', query:{name: 'userName'}});
this.$route.query.name;    //you
//此時路由爲:"http://example.com/#/login?name=userName。"
複製代碼
  1. $route.redirectedFrom
    字符串(string)。重定向來源:
如:{ path: '*',redirect: {name: 'hello'}}
	此時訪問不存在的路由http://example.com/#/a會重定向到hello,
在hello訪問this.$route.redirectedFrom; 輸出「/a」。
複製代碼
  1. $route.matched
    數組(array)。當前路由下路由聲明的全部信息,從父路由(若是有)到當前路由爲止。
  2. $route.hash
    字符串(string)。當前路徑的hash值。

4、vue監聽$route的方式

watch:{‘$route’ (to, from) {}}
複製代碼

route 做爲vue實例的一個響應式屬性,和在data中寫的屬性本質上是同樣的,均可以經過this的方式拿到。既然你能夠監聽data中的屬性變化,一樣也能夠監聽route 的變化。watch中監聽的對象默認回調函數中的參數值就是newVal,oldVal。做爲 $route 屬性來講固然也就是 to 和 from 的概念了。
Vue用router.push(傳參)跳轉頁面,參數改變,在跳轉後的路由觀察路由變化,進行頁面刷新,可對「from->to」的過程設置動畫效果。
該功能的難點就在於怎樣獲取「上一頁」和「下一頁」,即怎樣分辨是「前進」仍是「後退」?
例:bash

// watch $route 決定使用哪一種過渡
watch:{
    '$route' (to, from) {
      //此時假設從index頁面跳轉到pointList頁面
      console.log(to); // "/pointList"
      console.log(from); // 「/index」
      const routeDeep = ['/', '/index','/pointList', '/settLement'];
      const toDepth = routeDeep.indexOf(to.path)
      const fromDepth = routeDeep.indexOf(from.path)
      this.transitionName = toDepth > fromDepth ? 'fold-left' : 'fold-right'
    }
  },
複製代碼

to、from是最基本的路由對象,分別表示從(from)某個頁面跳轉到(to)另外一個頁面,to.path(表示要跳轉到的路由地址),from.path同理。
定義routeDeep數組,將路由目錄按層級依次排序(暫不考慮嵌套路由的狀況),複雜單頁應用裏,同一層級(如同一頁面上的多個導航按鈕)順序隨意,而後依次排列每一個導航的下一頁、下下頁…即保證每一個「上一頁」在「下一頁」前面。
總結下來就是:按照routeDeep數組裏定義的路由目錄的順序,「toDepth > fromDepth」表示「上一頁」跳轉到「下一頁」,同理可由此判斷是「前進」仍是「後退」。app

5、Vue2.0中transition組件的使用

<transition :name="transitionName">
    <router-view class="view app-view"></router-view>
</transition>
複製代碼
  • transition中有name屬性用於替換vue鉤子函數中的類名。
  • transition中只能有一個子元素而且該子元素須要有v-show或者v-if來控制是否顯示。
過渡CSS類名

transition中的name屬性用於 替換 vue鉤子函數中的類名transitionName-模塊化

  • transitionName-enter: 定義進入過渡的開始狀態。在元素被插入時生效,在下一個幀移除。
  • transitionName-enter-active: 定義進入過渡的結束狀態。在元素被插入時生效,在transition/animation完成以後移除。
  • transitionName-leave:定義離開過渡的開始狀態。在離開過渡被觸發時生效,在下一個幀移除。
  • transitionName-leave-active: 定義離開過渡的結束狀態。在離開過渡被觸發時生效,在transition/animation完成以後移除。
this.transitionName = toDepth > fromDepth ? 'fold-left' : 'fold-right'
複製代碼

在「watch $route」中,判斷頁面跳轉的「前進」和「後退」時,決定用不一樣的過渡效果(fold-left仍是fold-right)。

6、animation、transform動畫效果實現

在上一個主題中,判斷頁面跳轉路徑以後,爲兩種跳轉的transition設置不一樣的類名「fold-left」、「fold-right」。
而後在CSS中,爲兩種類名設置不一樣的動畫效果(這裏以「左滑動」和「右滑動」爲例):

.fold-left-enter-active {
    animation-name: fold-left-in;
    animation-duration: .3s;
  }
  .fold-left-leave-active {
    animation-name: fold-left-out;
    animation-duration: .3s;
  }
.fold-right-enter-active {
    animation-name: fold-right-in;
    animation-duration: .3s;
  }
  .fold-right-leave-active {
    animation-name: fold-right-out;
    animation-duration: .3s;
  }
複製代碼

animation 屬性是一個簡寫屬性,用於設置六個動畫屬性:

描述
animation-name 規定須要綁定到選擇器的 keyframe 名稱。
animation-duration 規定完成動畫所花費的時間,以秒或毫秒計。
animation-timing-function 規定動畫的速度曲線。
animation-delay 規定在動畫開始以前的延遲。
animation-iteration-count 規定動畫應該播放的次數。
animation-direction 規定是否應該輪流反向播放動畫。
@keyframes fold-left-in {
    0% {
      transform: translate3d(100%, 0, 0);
    }
    100% {
      transform: translate3d(0, 0, 0);
    }
  }
  @keyframes fold-left-out {
    0% {
      transform: translate3d(0, 0, 0);
    }
    100% {
      transform: translate3d(-100%, 0, 0);
    }
  }
複製代碼

根據CSS3 @keyframes規則,建立動畫。建立動畫的原理即將一套CSS樣式逐漸變化爲另外一套樣式。在動畫過程當中,可以屢次改變這套CSS樣式。能夠「百分比」來規定改變發生的時間,或者經過關鍵詞「from」和「to」,等價於「0%」(動畫的開始時間)和「100%」(動畫的結束時間)。通常爲了得到最佳的瀏覽器支持,應該始終定義0%和100%選擇器。
transform屬性向元素應用2D或3D轉換。該屬性容許咱們對元素進行旋轉、縮放、移動或傾斜。translate3d(x,y,z)定義3D轉換,如transform:translate3d(100%, 0, 0)只改變了x的值,即表明橫向左滑動,同理可相應推出其餘狀況。

7、寫在後面的坑 -- 頁面切換時空白閃屏的問題

優化前:

每次切換的時候,因爲原頁面佔着主頁面的位置,其他頁面,因爲頁面div自己是block元素,因此其餘block元素會另起一行,因此每次切換頁面時至關於從下面調出新頁面,因此會有一瞬的空白是從下面調出下一頁到主頁面的平行頁的過程,再執行動畫過渡命令。

解決:

給頁面CSS添加設置「position:absolute;」,此時頁面脫離文檔流,不佔空間,這樣就不會把下一頁擠下去,完成平滑過渡。 優化後:

暫時只用到了這個方法解決,可能也存在必定的弊端,若是有更好的方法,歡迎你們交流噢。

最後附上demo的代碼地址:vue頁面跳轉動畫效果demo

總結

以上就是vue頁面跳轉動畫效果功能實現的6個步驟,即這個功能中所含括的6個大知識點,固然其中還包括許多擴展的知識點,學無止境,需慢慢深刻挖掘…

相關文章
相關標籤/搜索