vue开发公共组件之返回顶部

 更新时间:2022年01月06日 09:52:32   作者:一键写代码  
这篇文章主要为大家详细介绍了vue开发公共组件之返回顶部,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了vue开发公共组件之返回顶部的具体代码,供大家参考,具体内容如下

记录一下开发公共组件的流程。

背景:pc端使用element-ui框架,本身是有返回顶部的组件的。现在需要在移动端使用。照着葫芦画瓢弄一个。
记录如何将公共组件通过install的方式,注册为全局的组件使用。

components目录下,新建bacttop文件夹,内部包含一个index.js文件和一个src文件夹。
src文件夹内放backtop.vue组件文件。

|--components
   |--index.js
   |-- backtop
       |--index.js
       |--src
             |--backtop.vue

backtop下的index.js负责安装,backtop.vue内部写具体的组件代码

index.js文件内容:

// index.js
import Backtop from "./src/backtop"; // 引入组件

// 配置安装方法
/* istanbul ignore next */
Backtop.install = function (Vue) {
  Vue.component(Backtop.name, Backtop);
};

// 导出模块
export default Backtop;

backtop.vue文件内容:

<template>
 <!-- xl-backtop样式名,需要自己在样式文件中定义这个样式内容 -->
  <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>
// 这里引入了节流函数
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>

返回顶部的样式内容:

// 返回顶部
.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]; // 其他的组件以数组形式继续写
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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈一下Vue生命周期中mounted和created的区别

    浅谈一下Vue生命周期中mounted和created的区别

    每一个vue实例从创建到销毁的过程,就是这个vue实例的生命周期,在这个过程中,他经历了从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程,那么这些过程中,具体vue做了些啥,我们今天来了解一下
    2023-05-05
  • 关于eslint和prettier格式化冲突问题

    关于eslint和prettier格式化冲突问题

    这篇文章主要介绍了eslint和prettier格式化冲突问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • mapbox gl开箱即用的地图引擎库

    mapbox gl开箱即用的地图引擎库

    这篇文章主要为大家介绍了一款mapbox gl开箱即用的地图引擎库,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • vue 2.8.2版本配置刚进入时候的默认页面方法

    vue 2.8.2版本配置刚进入时候的默认页面方法

    今天小编就为大家分享一篇vue 2.8.2版本配置刚进入时候的默认页面方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue中使用animate.css实现炫酷动画效果

    vue中使用animate.css实现炫酷动画效果

    这篇文章主要介绍了vue中使用animate.css实现动画效果,我们使用它,只需要写很少的代码,就可以实现非常炫酷的动画效果,感兴趣的朋友跟随小编一起看看吧
    2022-04-04
  • vue轻量级框架无法获取到vue对象解决方法

    vue轻量级框架无法获取到vue对象解决方法

    这篇文章主要介绍了vue轻量级框架无法获取到vue对象解决方法相关知识点,有需要的读者们跟着学习下。
    2019-05-05
  • vue全局引入scss(mixin)

    vue全局引入scss(mixin)

    本文主要介绍了 vue全局引入scss,我们在写VUE的时候,会使用scss,也会做一些通用样式,方便使用,在写好的通用样式的时候,每次都要单文件导入,刚开始写的时候,感觉还好,后面工程量大了后,就显得麻烦,那么本文就全局导入scss样式,下面来看详细内容,需要的朋友可以参考一下
    2021-11-11
  • vue生命周期和react生命周期对比【推荐】

    vue生命周期和react生命周期对比【推荐】

    本文通过实例代码给大家介绍了vue生命周期和react生命周期对比 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • Vue全局监测错误并生成错误日志实现方法介绍

    Vue全局监测错误并生成错误日志实现方法介绍

    在做完一个项目后,之后的维护尤为重要。这时,如果项目配置了错误日志记录,这样能大大减少维护难度。虽然不一定能捕获到全部的错误,但是一般的错误还是可以监测到的。这样就不用测试人员去一遍一遍复现bug了
    2022-10-10
  • 一篇文章让你看懂封装Axios

    一篇文章让你看懂封装Axios

    axios的封装和api接口的统一管理,其实主要目的就是在帮助我们简化代码和利于后期的更新维护,这篇文章主要给大家介绍了关于封装Axios的相关资料,需要的朋友可以参考下
    2022-01-01

最新评论