使用vue制作FullPage頁面滾動效果
前言
已經(jīng)有好久沒有更新博客了,大三下了要準備找實習了,才發(fā)現(xiàn)自己很多東西都不會,所以趕緊找了個現(xiàn)在流行的MVVM框架學習一下。我學習的是Vue,所以拿Vue寫了一個FullPage的模板,可以供自己和其他人使用。
項目的地址是:https://github.com/hzxszsk/vue-fullpage
項目講解
為了加深理解,我把我制作這個FullPage頁面的思路和流程記錄下來,也可以給其他和我一樣的初學者一個參考。
分解思路
首先,我根據(jù)Vue的組件開發(fā)思想,把這個FullPage頁面分為兩個主要的組件模塊:頁面組件(Page)和頁面控制組件(PageController)。除了這兩個組件模塊之外,還有一個整合的App.vue文件。
其中,Page組件主要負責每個FullPage頁面的樣式和位置控制,而PageController組件則用來發(fā)起頁面的切換請求。
因為Vue是單向數(shù)據(jù)流形式的,因此將所有需要的數(shù)據(jù)都定義在App.vue文件中,由App組件向下傳遞數(shù)據(jù)。
數(shù)據(jù)需求分析
要制作一個FullPage頁面,每個Page頁面需要的是頁面自身的內(nèi)容(頁面的內(nèi)容和樣式配置),而控制器所需要的數(shù)據(jù)有當前正在顯示的頁面以及總的頁面數(shù),用這兩個屬性計算出其他需要的屬性。
其中,總頁面數(shù)即是Page總數(shù),有多少個Page,就有多少個Page的配置,因此可以通過計算Page配置信息對象的數(shù)量來獲得總頁面數(shù)。
我在App.vue的組件data中定義了兩個屬性:
- currentPage表示的是當前頁面的序號(從1開始計算);
- options是一個數(shù)組,其中的每一個對象表示的是對應序號的頁面的配置信息,可以通過修改里面的對象屬性從而改變對應Page的樣式。
Page組件只需要知道當前頁面是第幾個頁面和自身的配置,因此只含有兩個屬性:
- currentPage
- option 表示自身的配置
PageController需要對頁面進行切換控制,因此需要兩個屬性:
- currentPage
- pageNum 表示總的頁面數(shù)量
編寫頁面樣式
App組件的結構為:
<div id="app" class="app"> <!-- page為單獨的頁面組件,page內(nèi)可以編寫任意的頁面內(nèi)容 --> <page :currentPage="currentPage"></page> <!-- page-controller為控制器組件 --> <page-controller :pageNum="pageNum" :currentPage="currentPage" @changePage="changePage" :arrowsType="arrowsType"></page-controller> </div>
App組件主要樣式:
/* 頁面寬高為100%,overflow為hidden隱藏溢出部分 */ html,body { margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden; } .app { height: 100%; width: 100%; }
Page組件結構為:
<section class="page" v-if="options" :style="{background:options.background,color:options.color||'#fff'}" :class="{'page-before': options.index < currentPage,'page-after': options.index > currentPage}"> <div :class="{'page-center': options.isCenter}"> <slot></slot> </div> </section> <section class="page" v-else>頁面正在渲染中。。。</section>
其中slot內(nèi)為在App.vue的page標簽內(nèi)編寫的html內(nèi)容,并且根據(jù)Page組件內(nèi)的option屬性,為Page頁面添加不同的樣式(包括背景顏色、字體顏色、居中等,而且可以自由擴展)
Page組件的主要樣式為:
.page { position: absolute; width: 100%; height: 100%; transition: all 0.5s ease 0s; } .page-before { transform: translate3d(0,-100%,0); } .page-after { transform: translate3d(0,100%,0); }
通過比較當前頁面的index與currentPage的大小,可以判斷Page組件處于之前的頁面,當前的頁面和之后的頁面三個狀態(tài)中的哪一種。
將所有頁面都用absolute定位在同一個位置上,對于處于之前的頁面的Page,添加page-before類標簽,使其在Y軸上向上偏移自身高度距離,同理,對之后的頁面做Y軸上向下的自身高度偏移。
在page標簽上添加transition樣式,使其在切換時可以產(chǎn)生動畫效果。
PageController組件的結構為:
<nav class="controller"> <button v-if="arrowsType != 'no'" class="prev-btn" :class="{moving:arrowsType === 'animate'}" @click="changePage(prevIndex)"></button> <ul> <li @click="changePage(index)" v-for="index in pageNum" :key="'controller-'+index" class="controller-item"></li> </ul> <button v-if="arrowsType != 'no'" class="next-btn" :class="{moving:arrowsType === 'animate'}" @click="changePage(nextIndex)"></button> </nav>
PageController組件中分為兩塊,控制上下滾動的上下箭頭按鈕和控制所有頁面的ul列表。
因為PageController中的樣式較多,因此不在文章中詳細說明,只做簡單介紹。
button和ul標簽用fixed定位,使其處于整個頁面的上方、下方和右側。
button使用rotate和border屬性,制作出箭頭的樣式,并添加對應的動畫效果(可以通過傳遞props選擇關閉)。
編寫頁面邏輯
切換頁面邏輯
因為所有的頁面切換都是由PageController發(fā)起,而控制currentPage的組件并不是PageController,所以需要有一個父子組件事件,由子組件PageController發(fā)起,傳遞一個參數(shù)表示要切換到第幾個頁面,因此在PageController中定義一個method:
changePage (index) { this.$emit('changePage', index); }
父組件接受該事件并調(diào)用自己定義的changePage方法,修改自身的currentPage屬性
changePage (index) { // 改變page this.currentPage = index; }
箭頭按鈕上下滾動
為了實現(xiàn)上下滾動,需要知道當前頁面的前一個頁面和后一個頁面分別是第幾個頁面,因此可以使用計算屬性,計算出前一個和后一個頁面的index值:
// PageController.vue nextIndex () { if (this.currentPage === this.pageNum) { return 1; } else { return this.currentPage + 1; } }, prevIndex () { if (this.currentPage === 1) { return this.pageNum; } else { return this.currentPage - 1; } }
在點擊箭頭時,將對應的nextIndex或prevIndex值當做參數(shù)傳給changePage方法。
滾輪滾動和移動端滾動
滾輪滾動和移動端滾動主要依靠window的監(jiān)聽事件,根據(jù)傳入的event屬性,計算出頁面是應該向上還是向下滾動,將需要滾動的方向作為參數(shù)傳遞給處理函數(shù)handler。
因為代碼略長,因此不全部顯示在文章中,只顯示處理函數(shù)相關邏輯
let _this = this; let timer = null; function scrollHandler (direction) { // 防止重復觸發(fā)滾動事件 if (timer != null) { return; } if (direction === 'down') { _this.changePage(_this.nextIndex); } else { _this.changePage(_this.prevIndex); } timer = setTimeout(function() { clearTimeout(timer); timer = null; }, 500); }
需要注意的一點是,移動端做滾動判斷時,要求touches和changedTouches之間需要一定的間隔,不然容易誤觸發(fā)滾動事件。
OPTIONS屬性的分發(fā)
為了使使用者更加方便地編寫頁面內(nèi)容而不在意具體的頁面序號,我采用了自動對page內(nèi)的option賦值的方法。其實現(xiàn)原理是在App.vue文件中,使用鉤子函數(shù)mounted,對page中的option屬性進行設置。
mounted () { this.$children.forEach((child, index) => { // 動態(tài)設置各個page內(nèi)的options if (child.option === null) { let childOption = this.options[index]; this.$set(childOption,'index',index+1); child.option = childOption; } }); }
高級屬性:新的鉤子函數(shù)
為了滿足部分使用者的需求,我在設置了兩個鉤子函數(shù):beforeLeave和afterEnter。
這兩個鉤子函數(shù)可以設置在對應頁面的options屬性對象中,并且含有一個默認的參數(shù),為對應頁面的page組件實例對象。
其實現(xiàn)方式為在原先的changePage函數(shù)(App.vue)內(nèi)添加新的邏輯:
changePage (index) { // beforeLeave let beforeIndex = this.currentPage - 1; let leaveFunction = this.options[beforeIndex].beforeLeave; typeof leaveFunction === 'function' && leaveFunction.call(this,this.$children[beforeIndex]); // 改變page this.currentPage = index; // afterEnter let nextIndex = index-1; let enterFunction = this.options[nextIndex].afterEnter; this.$nextTick(function () { typeof enterFunction === 'function' && enterFunction.call(this,this.$children[nextIndex]); }) }
總結
這篇文章記錄了我開發(fā)一個FullPage頁面的總體流程,將主要的邏輯重新順理了一遍,還有一些小的細節(jié)沒有寫在文章中,有興趣的可以去具體的項目頁面看源碼
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- 解決Vue頁面固定滾動位置的處理辦法
- vue監(jiān)聽滾動事件實現(xiàn)滾動監(jiān)聽
- Vue.js實戰(zhàn)之通過監(jiān)聽滾動事件實現(xiàn)動態(tài)錨點
- vue實現(xiàn)消息的無縫滾動效果的示例代碼
- vue elementUI table表格數(shù)據(jù) 滾動懶加載的實現(xiàn)方法
- vue中使用vue-router切換頁面時滾動條自動滾動到頂部的方法
- 詳解 vue better-scroll滾動插件排坑
- vue實現(xiàn)ajax滾動下拉加載,同時具有l(wèi)oading效果(推薦)
- vue使用mint-ui實現(xiàn)下拉刷新和無限滾動的示例代碼
- vue實現(xiàn)廣告欄上下滾動效果
相關文章
vue中的echarts實現(xiàn)寬度自適應的解決方案
這篇文章主要介紹了vue中的echarts實現(xiàn)寬度自適應,本文給大家分享實現(xiàn)方案,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09vue實現(xiàn)動態(tài)添加數(shù)據(jù)滾動條自動滾動到底部的示例代碼
本篇文章主要介紹了vue實現(xiàn)動態(tài)添加數(shù)據(jù)滾動條自動滾動到底部的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07解決antd 下拉框 input [defaultValue] 的值的問題
這篇文章主要介紹了解決antd 下拉框 input [defaultValue] 的值的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10使用vue自定義指令開發(fā)表單驗證插件validate.js
今天就來介紹一下如何利用vue的自定義指令directive來開發(fā)一個表單驗證插件的過程,需要的朋友可以參考下2019-05-05