Vue實現(xiàn)一個返回頂部backToTop組件
最近在學(xué)習(xí)VUE。自己就在研究怎么用VUE實現(xiàn)一個組件的封裝,今日就算留個筆記
前言
返回頂部這個功能用jq實現(xiàn),好容易實現(xiàn),一個animate配合scrollTo就搞定了
今天我們來試試vue封裝一個原生js實現(xiàn)的返回頂部;
寫起來夠嗆,借助github,看了別人的gist,稍微封裝了下;
當(dāng)然不是用scrollTo直接調(diào)位那種,沒有過渡效果怎么說得過去!!還是搗鼓出來了.
廢話不多說,看效果圖…
效果圖

實現(xiàn)思路
- 過渡用的是requestAnimationFrame,這貨只支持IE10+,所以必須做兼容
- 滾動視圖是window.pageYOffset,這貨支持IE9+;
- 為了讓可控性更強,圖標(biāo)采用iconfont,具體瞅代碼
你能學(xué)到什么?
- 學(xué)到一些頁面計算相關(guān)的東東
- 動畫API的一些知識
- Vue封裝組件相關(guān)知識和生命周期和事件監(jiān)聽銷毀相關(guān)知識的運用
實現(xiàn)功能
- 視圖默認(rèn)在350處顯示返回頂部的按鈕和圖標(biāo)
- 提示文字和顏色,在圖標(biāo)上下左右的自定義,字段都限制了格式和默認(rèn)值
- 圖標(biāo)顏色和形狀,大小的自定義,字段都限制了格式和默認(rèn)值
- 過渡動效的自定義,用法:scrollIt(0, 1500, 'easeInOutCubic', callback);
- 返回到視圖的point,也就是滾動到哪里
- 過渡時間(ms級別)
- 一堆過渡效果,字符串格式,其實就是滾動的計算函數(shù)..
- 當(dāng)然少不了默認(rèn)參數(shù)了,除了callback
- 兼容性是IE9+,特意開了虛擬機去嘗試
代碼
scrollIt.js –過渡滾動實現(xiàn)
export function scrollIt(
destination = 0,
duration = 200,
easing = "linear",
callback
) {
// define timing functions -- 過渡動效
let easings = {
// no easing, no acceleration
linear(t) {
return t;
},
// accelerating from zero velocity
easeInQuad(t) {
return t * t;
},
// decelerating to zero velocity
easeOutQuad(t) {
return t * (2 - t);
},
// acceleration until halfway, then deceleration
easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
// accelerating from zero velocity
easeInCubic(t) {
return t * t * t;
},
// decelerating to zero velocity
easeOutCubic(t) {
return --t * t * t + 1;
},
// acceleration until halfway, then deceleration
easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
// accelerating from zero velocity
easeInQuart(t) {
return t * t * t * t;
},
// decelerating to zero velocity
easeOutQuart(t) {
return 1 - --t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuart(t) {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
},
// accelerating from zero velocity
easeInQuint(t) {
return t * t * t * t * t;
},
// decelerating to zero velocity
easeOutQuint(t) {
return 1 + --t * t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuint(t) {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
}
};
// requestAnimationFrame()的兼容性封裝:先判斷是否原生支持各種帶前綴的
//不行的話就采用延時的方案
(function() {
var lastTime = 0;
var vendors = ["ms", "moz", "webkit", "o"];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame =
window[vendors[x] + "RequestAnimationFrame"];
window.cancelAnimationFrame =
window[vendors[x] + "CancelAnimationFrame"] ||
window[vendors[x] + "CancelRequestAnimationFrame"];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
})();
function checkElement() {
// chrome,safari及一些瀏覽器對于documentElemnt的計算標(biāo)準(zhǔn)化,reset的作用
document.documentElement.scrollTop += 1;
let elm =
document.documentElement.scrollTop !== 0
? document.documentElement
: document.body;
document.documentElement.scrollTop -= 1;
return elm;
}
let element = checkElement();
let start = element.scrollTop; // 當(dāng)前滾動距離
let startTime = Date.now(); // 當(dāng)前時間
function scroll() { // 滾動的實現(xiàn)
let now = Date.now();
let time = Math.min(1, (now - startTime) / duration);
let timeFunction = easings[easing](time);
element.scrollTop = timeFunction * (destination - start) + start;
if (element.scrollTop === destination) {
callback; // 此次執(zhí)行回調(diào)函數(shù)
return;
}
window.requestAnimationFrame(scroll);
}
scroll();
}
backToTop.vue
<template>
<div class="back-to-top" @click="backToTop" v-show="showReturnToTop" @mouseenter="show" @mouseleave="hide">
<i :class="[bttOption.iClass]" :style="{color:bttOption.iColor,'font-size':bttOption.iFontsize}"></i>
<span class="tips" :class="[bttOption.iPos]" :style="{color:bttOption.textColor}" v-show="showTooltips">{{bttOption.text}}</span>
</div>
</template>
<script>
import { scrollIt } from './scrollIt'; // 引入動畫過渡的實現(xiàn)
export default {
name: 'back-to-top',
props: {
text: { // 文本提示
type: String,
default: '返回頂部'
},
textColor: { // 文本顏色
type: String,
default: '#f00'
},
iPos: { // 文本位置
type: String,
default: 'right'
},
iClass: { // 圖標(biāo)形狀
type: String,
default: 'fzicon fz-ad-fanhuidingbu1'
},
iColor: { // 圖標(biāo)顏色
type: String,
default: '#f00'
},
iFontsize: { // 圖標(biāo)大小
type: String,
default: '32px'
},
pageY: { // 默認(rèn)在哪個視圖顯示返回按鈕
type: Number,
default: 400
},
transitionName: { // 過渡動畫名稱
type: String,
default: 'linear'
}
},
data: function () {
return {
showTooltips: false,
showReturnToTop: false
}
},
computed: {
bttOption () {
return {
text: this.text,
textColor: this.textColor,
iPos: this.iPos,
iClass: this.iClass,
iColor: this.iColor,
iFontsize: this.iFontsize
}
}
},
methods: {
show () { // 顯示隱藏提示文字
return this.showTooltips = true;
},
hide () {
return this.showTooltips = false;
},
currentPageYOffset () {
// 判斷滾動區(qū)域大于多少的時候顯示返回頂部的按鈕
window.pageYOffset > this.pageY ? this.showReturnToTop = true : this.showReturnToTop = false;
},
backToTop () {
scrollIt(0, 1500, this.transitionName, this.currentPageYOffset);
}
},
created () {
window.addEventListener('scroll', this.currentPageYOffset);
},
beforeDestroy () {
window.removeEventListener('scroll', this.currentPageYOffset)
}
}
</script>
<style scoped lang="scss">
.back-to-top {
position: fixed;
bottom: 5%;
right: 100px;
z-index: 9999;
cursor: pointer;
width: auto;
i {
font-size: 32px;
display: inline-block;
position: relative;
text-align: center;
padding: 5px;
background-color: rgba(234, 231, 231, 0.52);
border-radius: 5px;
transition: all 0.3s linear;
&:hover {
border-radius: 50%;
background: #222;
color: #fff !important;
}
}
.tips {
display: inline-block;
position: absolute;
word-break: normal;
white-space: nowrap;
width: auto;
font-size: 12px;
color: #fff;
z-index: -1;
}
.left {
right: 0;
top: 50%;
margin-right: 50px;
transform: translateY(-50%);
}
.right {
left: 0;
top: 50%;
margin-left: 50px;
transform: translateY(-50%);
}
.bottom {
bottom: 0;
margin-top: 50px;
}
.top {
top: 0;
margin-bottom: 50px;
}
}
</style>
總結(jié)
從心血來潮到折騰出來,為了兼顧兼容性和拓展性,好像幾個小時了.
不過實現(xiàn)了.你再搬到其他語言,類似ng4,也就是十來分鐘的事情,
思路會了,實現(xiàn)更多的是寫法而已,至于性能優(yōu)化,可以一邊寫一邊考慮,也可以實現(xiàn)后有空再優(yōu)化.
希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue組件傳值方式(props屬性,父到子,子到父,兄弟傳值)
這篇文章主要介紹了Vue組件傳值方式(props屬性,父到子,子到父,兄弟傳值),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
Vue?transition組件簡單實現(xiàn)數(shù)字滾動
這篇文章主要為大家介紹了Vue?transition組件簡單實現(xiàn)數(shù)字滾動示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Vue中JS動畫與Velocity.js的結(jié)合使用
這篇文章主要介紹了Vue中JS動畫與Velocity.js的結(jié)合使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02
vue element 多圖片組合預(yù)覽的實現(xiàn)
本文主要介紹了vue element多圖片預(yù)覽實現(xiàn)的相關(guān)資料,最近的項目中有圖片預(yù)覽的場景,本文就來介紹一下如何使用,感興趣的可以了解一下2023-08-08
vue實現(xiàn)未登錄訪問其他頁面自動跳轉(zhuǎn)登錄頁功能(實現(xiàn)步驟)
這篇文章主要介紹了vue實現(xiàn)未登錄下訪問其他頁面自動跳轉(zhuǎn)登錄頁,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07

