vue開(kāi)發(fā)公共組件之返回頂部
本文實(shí)例為大家分享了vue開(kāi)發(fā)公共組件之返回頂部的具體代碼,供大家參考,具體內(nèi)容如下
記錄一下開(kāi)發(fā)公共組件的流程。
背景:pc端使用element-ui框架,本身是有返回頂部的組件的。現(xiàn)在需要在移動(dòng)端使用。照著葫蘆畫(huà)瓢弄一個(gè)。
記錄如何將公共組件通過(guò)install的方式,注冊(cè)為全局的組件使用。
components目錄下,新建bacttop文件夾,內(nèi)部包含一個(gè)index.js文件和一個(gè)src文件夾。
src文件夾內(nèi)放backtop.vue組件文件。
|--components
|--index.js
|-- backtop
|--index.js
|--src
|--backtop.vue
backtop下的index.js負(fù)責(zé)安裝,backtop.vue內(nèi)部寫(xiě)具體的組件代碼
index.js文件內(nèi)容:
// index.js import Backtop from "./src/backtop"; // 引入組件 // 配置安裝方法 /* istanbul ignore next */ Backtop.install = function (Vue) { ? Vue.component(Backtop.name, Backtop); }; // 導(dǎo)出模塊 export default Backtop;
backtop.vue文件內(nèi)容:
<template> ?<!-- xl-backtop樣式名,需要自己在樣式文件中定義這個(gè)樣式內(nèi)容 --> ? <div ? ? v-if="visible" ? ? @click.stop="handleClick" ? ? :style="{ ? ? ? right: styleRight, ? ? ? bottom: styleBottom, ? ? }" ? ? class="xl-backtop" ? > ? ? <slot> ? ? <!-- 這里是返回頂部的圖標(biāo) --> ? ? ? <van-icon name="arrow-up" /> ? ? </slot> ? </div> </template> <script> // 這里引入了節(jié)流函數(shù) import { _throttle } from "@/utils"; const cubic = (value) => Math.pow(value, 3); const easeInOutCubic = (value) => ? value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2; export default { ? name: "XlBacktop", ? props: { ? ? visibilityHeight: { ? ? ? type: Number, ? ? ? default: 200, ? ? }, ? ? target: [String], ? ? right: { ? ? ? type: Number, ? ? ? default: 40, ? ? }, ? ? bottom: { ? ? ? type: Number, ? ? ? default: 40, ? ? }, ? }, ? data() { ? ? return { ? ? ? el: null, ? ? ? container: null, ? ? ? visible: false, ? ? }; ? }, ? computed: { ? ? styleBottom() { ? ? ? return `${this.bottom}px`; ? ? }, ? ? styleRight() { ? ? ? return `${this.right}px`; ? ? }, ? }, ? mounted() { ? ? this.init(); ? ? this.throttledScrollHandler = _throttle(this.onScroll, 300); ? ? this.container.addEventListener("scroll", this.throttledScrollHandler); ? }, ? methods: { ? ? init() { ? ? ? this.container = document; ? ? ? this.el = document.documentElement; ? ? ? if (this.target) { ? ? ? ? this.el = document.querySelector(this.target); ? ? ? ? if (!this.el) { ? ? ? ? ? throw new Error(`target is not existed: ${this.target}`); ? ? ? ? } ? ? ? ? this.container = this.el; ? ? ? } ? ? }, ? ? onScroll() { ? ? ? const scrollTop = this.el.scrollTop; ? ? ? this.visible = scrollTop >= this.visibilityHeight; ? ? }, ? ? handleClick(e) { ? ? ? this.scrollToTop(); ? ? ? this.$emit("click", e); ? ? }, ? ? scrollToTop() { ? ? ? const el = this.el; ? ? ? const beginTime = Date.now(); ? ? ? const beginValue = el.scrollTop; ? ? ? const rAF = ? ? ? ? window.requestAnimationFrame || ((func) => setTimeout(func, 16)); ? ? ? const frameFunc = () => { ? ? ? ? const progress = (Date.now() - beginTime) / 500; ? ? ? ? if (progress < 1) { ? ? ? ? ? el.scrollTop = beginValue * (1 - easeInOutCubic(progress)); ? ? ? ? ? rAF(frameFunc); ? ? ? ? } else { ? ? ? ? ? el.scrollTop = 0; ? ? ? ? } ? ? ? }; ? ? ? rAF(frameFunc); ? ? }, ? }, ? beforeDestroy() { ? ? this.container.removeEventListener("scroll", this.throttledScrollHandler); ? }, }; </script>
返回頂部的樣式內(nèi)容:
// 返回頂部 .xl-backtop { ? ?position: fixed; ? width: 40px; ? height: 40px; ? display: flex; ? justify-content: center; ? align-items: center; ? font-size: 20px; ? cursor: pointer; ? box-shadow: 0 0 6px rgba(0, 0, 0, 0.12); ? border-radius: 50%; ? z-index: 5; }
為了一次性注冊(cè)多個(gè)自己寫(xiě)的功能組件,我們?cè)赾omponents文件夾下面寫(xiě)一個(gè)index.js
components下的index負(fù)責(zé)一次性組合多個(gè)
// components/index.js import BackTop from "./backtop"; // 引入我們的返回頂部組件。其他的類似的一起寫(xiě)在這里 const components = [BackTop]; // 其他的組件以數(shù)組形式繼續(xù)寫(xiě) const install = function (Vue, opts = {}) { ? components.map((component) => { ? ? Vue.component(component.name, component); ? }); }; /* istanbul ignore if */ if (typeof window !== "undefined" && window.Vue) { ? install(window.Vue); } // 組合導(dǎo)出安裝方法 const exportsResult = { ? version: "1.0.0", ? install, }; Object.assign(exportsResult, components); export default exportsResult;
最后在項(xiàng)目的main.js安裝
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from "vue"; import App from "./App"; import store from "./store"; import router from "./router"; // 自己封裝的公共安裝組件 import XlComponent from "@/components"; Vue.use(XlComponent); import "@/styles/index.less"; // 全局 css Vue.config.productionTip = false; /* eslint-disable no-new */ new Vue({ ? el: "#app", ? router, ? store, ? components: { App }, ? template: "<App/>", });
補(bǔ)充:上述方法在安卓端會(huì)失效
原因是document.documentElement.scrollTop在安卓端始終是0;只有pc端和IOS端才是正常的。
改寫(xiě)backtop組件中的代碼,完成兼容。
<template> ? <transition name="van-fade"> ? ? <div ? ? ? v-if="visible" ? ? ? @click.stop="handleClick" ? ? ? :style="{ ? ? ? ? right: styleRight, ? ? ? ? bottom: styleBottom, ? ? ? }" ? ? ? class="xl-backtop" ? ? > ? ? ? <slot> ? ? ? ? <van-icon name="arrow-up" color="#13b7f6" /> ? ? ? </slot> ? ? </div> ? </transition> </template> <script> import { _throttle } from "@/utils"; const cubic = (value) => Math.pow(value, 3); const easeInOutCubic = (value) => ? value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2; export default { ? name: "XlBacktop", ? props: { ? ? visibilityHeight: { ? ? ? type: Number, ? ? ? default: 200, ? ? }, ? ? target: [String], ? ? right: { ? ? ? type: Number, ? ? ? default: 40, ? ? }, ? ? bottom: { ? ? ? type: Number, ? ? ? default: 40, ? ? }, ? }, ? data() { ? ? return { ? ? ? el: null, ? ? ? container: null, ? ? ? visible: false, ? ? }; ? }, ? computed: { ? ? styleBottom() { ? ? ? return `${this.bottom}px`; ? ? }, ? ? styleRight() { ? ? ? return `${this.right}px`; ? ? }, ? }, ? mounted() { ? ? this.init(); ? ? this.throttledScrollHandler = _throttle(this.onScroll, 300); ? ? this.container.addEventListener("scroll", this.throttledScrollHandler); ? }, ? methods: { ? ? init() { ? ? ? this.container = document; ? ? ? this.el = document.documentElement; ? ? ? if (this.target) { ? ? ? ? this.el = document.querySelector(this.target); ? ? ? ? if (!this.el) { ? ? ? ? ? throw new Error(`target is not existed: ${this.target}`); ? ? ? ? } ? ? ? ? this.container = this.el; ? ? ? } ? ? }, ? ? onScroll() { ? ? // 這里,如果document.documentElement.scrollTop 的值為0,就獲取document.body.scrollTop ? ? ? const scrollTop = this.el.scrollTop || document.body.scrollTop; ? ? ? this.visible = scrollTop >= this.visibilityHeight; ? ? }, ? ? handleClick(e) { ? ? ? this.scrollToTop(); ? ? ? this.$emit("click", e); ? ? }, ? ? scrollToTop() { ? ? // 還有這里,如果document.documentElement.scrollTop 的值為0,就獲取document.body元素 ? ? ? const el = this.el.scrollTop? this.el : document.body; ? ? ? const beginTime = Date.now(); ? ? ? const beginValue = el.scrollTop; ? ? ? const rAF = ? ? ? ? window.requestAnimationFrame || ((func) => setTimeout(func, 16)); ? ? ? const frameFunc = () => { ? ? ? ? const progress = (Date.now() - beginTime) / 500; ? ? ? ? if (progress < 1) { ? ? ? ? ? el.scrollTop = beginValue * (1 - easeInOutCubic(progress)); ? ? ? ? ? rAF(frameFunc); ? ? ? ? } else { ? ? ? ? ? el.scrollTop = 0; ? ? ? ? } ? ? ? }; ? ? ? rAF(frameFunc); ? ? }, ? }, ? beforeDestroy() { ? ? this.container.removeEventListener("scroll", this.throttledScrollHandler); ? ? this.el = null; ? }, }; </script>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
淺談一下Vue生命周期中mounted和created的區(qū)別
每一個(gè)vue實(shí)例從創(chuàng)建到銷毀的過(guò)程,就是這個(gè)vue實(shí)例的生命周期,在這個(gè)過(guò)程中,他經(jīng)歷了從開(kāi)始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過(guò)程,那么這些過(guò)程中,具體vue做了些啥,我們今天來(lái)了解一下2023-05-05關(guān)于eslint和prettier格式化沖突問(wèn)題
這篇文章主要介紹了eslint和prettier格式化沖突問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08vue 2.8.2版本配置剛進(jìn)入時(shí)候的默認(rèn)頁(yè)面方法
今天小編就為大家分享一篇vue 2.8.2版本配置剛進(jìn)入時(shí)候的默認(rèn)頁(yè)面方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09vue中使用animate.css實(shí)現(xiàn)炫酷動(dòng)畫(huà)效果
這篇文章主要介紹了vue中使用animate.css實(shí)現(xiàn)動(dòng)畫(huà)效果,我們使用它,只需要寫(xiě)很少的代碼,就可以實(shí)現(xiàn)非常炫酷的動(dòng)畫(huà)效果,感興趣的朋友跟隨小編一起看看吧2022-04-04vue輕量級(jí)框架無(wú)法獲取到vue對(duì)象解決方法
這篇文章主要介紹了vue輕量級(jí)框架無(wú)法獲取到vue對(duì)象解決方法相關(guān)知識(shí)點(diǎn),有需要的讀者們跟著學(xué)習(xí)下。2019-05-05Vue全局監(jiān)測(cè)錯(cuò)誤并生成錯(cuò)誤日志實(shí)現(xiàn)方法介紹
在做完一個(gè)項(xiàng)目后,之后的維護(hù)尤為重要。這時(shí),如果項(xiàng)目配置了錯(cuò)誤日志記錄,這樣能大大減少維護(hù)難度。雖然不一定能捕獲到全部的錯(cuò)誤,但是一般的錯(cuò)誤還是可以監(jiān)測(cè)到的。這樣就不用測(cè)試人員去一遍一遍復(fù)現(xiàn)bug了2022-10-10