vue開發(fā)公共組件之返回頂部
本文實例為大家分享了vue開發(fā)公共組件之返回頂部的具體代碼,供大家參考,具體內(nèi)容如下
記錄一下開發(fā)公共組件的流程。
背景:pc端使用element-ui框架,本身是有返回頂部的組件的?,F(xiàn)在需要在移動端使用。照著葫蘆畫瓢弄一個。
記錄如何將公共組件通過install的方式,注冊為全局的組件使用。
components目錄下,新建bacttop文件夾,內(nèi)部包含一個index.js文件和一個src文件夾。
src文件夾內(nèi)放backtop.vue組件文件。
|--components
|--index.js
|-- backtop
|--index.js
|--src
|--backtop.vue
backtop下的index.js負責安裝,backtop.vue內(nèi)部寫具體的組件代碼
index.js文件內(nèi)容:
// index.js import Backtop from "./src/backtop"; // 引入組件 // 配置安裝方法 /* istanbul ignore next */ Backtop.install = function (Vue) { ? Vue.component(Backtop.name, Backtop); }; // 導出模塊 export default Backtop;
backtop.vue文件內(nèi)容:
<template> ?<!-- xl-backtop樣式名,需要自己在樣式文件中定義這個樣式內(nèi)容 --> ? <div ? ? v-if="visible" ? ? @click.stop="handleClick" ? ? :style="{ ? ? ? right: styleRight, ? ? ? bottom: styleBottom, ? ? }" ? ? class="xl-backtop" ? > ? ? <slot> ? ? <!-- 這里是返回頂部的圖標 --> ? ? ? <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; }
為了一次性注冊多個自己寫的功能組件,我們在components文件夾下面寫一個index.js
components下的index負責一次性組合多個
// components/index.js import BackTop from "./backtop"; // 引入我們的返回頂部組件。其他的類似的一起寫在這里 const components = [BackTop]; // 其他的組件以數(shù)組形式繼續(xù)寫 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); } // 組合導出安裝方法 const exportsResult = { ? version: "1.0.0", ? install, }; Object.assign(exportsResult, components); export default exportsResult;
最后在項目的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/>", });
補充:上述方法在安卓端會失效
原因是document.documentElement.scrollTop在安卓端始終是0;只有pc端和IOS端才是正常的。
改寫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>
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
淺談一下Vue生命周期中mounted和created的區(qū)別
每一個vue實例從創(chuàng)建到銷毀的過程,就是這個vue實例的生命周期,在這個過程中,他經(jīng)歷了從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程,那么這些過程中,具體vue做了些啥,我們今天來了解一下2023-05-05vue中使用animate.css實現(xiàn)炫酷動畫效果
這篇文章主要介紹了vue中使用animate.css實現(xiàn)動畫效果,我們使用它,只需要寫很少的代碼,就可以實現(xiàn)非常炫酷的動畫效果,感興趣的朋友跟隨小編一起看看吧2022-04-04Vue全局監(jiān)測錯誤并生成錯誤日志實現(xiàn)方法介紹
在做完一個項目后,之后的維護尤為重要。這時,如果項目配置了錯誤日志記錄,這樣能大大減少維護難度。雖然不一定能捕獲到全部的錯誤,但是一般的錯誤還是可以監(jiān)測到的。這樣就不用測試人員去一遍一遍復現(xiàn)bug了2022-10-10