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>

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

(0)

相关推荐

  • vue实现移动端返回顶部

    本文实例为大家分享了vue实现移动端返回顶部的具体代码,供大家参考,具体内容如下 HTML: <template> <div class="home"> <div v-for="ys in 100" :key="ys"> <p>1</p> </div> <div @click="back" class="back1" v-show

  • Vue实现一个返回顶部backToTop组件

    最近在学习VUE.自己就在研究怎么用VUE实现一个组件的封装,今日就算留个笔记 前言 返回顶部这个功能用jq实现,好容易实现,一个animate配合scrollTo就搞定了 今天我们来试试vue封装一个原生js实现的返回顶部; 写起来够呛,借助github,看了别人的gist,稍微封装了下; 当然不是用scrollTo直接调位那种,没有过渡效果怎么说得过去!!还是捣鼓出来了. 废话不多说,看效果图- 效果图 实现思路 过渡用的是requestAnimationFrame,这货只支持IE10+,所

  • Vue实现返回顶部按钮实例代码

    前言 本文主要介绍了Vue 实现返回顶部按钮的方法,下面话不多说,来直接看代码吧 实例代码: <template> <div class="scrollTop"> <div class="backTop" @click="backTop"> <button v-show="flag_scroll"> 返回顶部 </button> </div> //数据源

  • vue项目tween方法实现返回顶部的示例代码

    一.场景 tween.js是一款可生成平滑动画效果的js动画库 当你要实现一个返回顶部的功能时候你会怎么做,大部分人会使用document.body.scrollTop =0:这么写就实现了功能, 不过要更加的细腻一点我们不妨用tween的缓动来实现,看看效果如何吧. 之前我们写过tween的相关文章,这里不做介绍了. 二.代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l

  • vue进入页面时不在顶部,检测滚动返回顶部按钮问题及解决方法

    这里是本小白使用时遇到的问题及个人使用的方法可能并不完美. 1.监测浏览器滚动条滚动事件及滚动距离 dmounted() { window.addEventListener("scroll", this.gundong); }, destroyed() { window.removeEventListener("scroll", this.gundong); }, methods: { gundong() { var dis = document.documentE

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

    本文实例为大家分享了vue开发公共组件之返回顶部的具体代码,供大家参考,具体内容如下 记录一下开发公共组件的流程. 背景:pc端使用element-ui框架,本身是有返回顶部的组件的.现在需要在移动端使用.照着葫芦画瓢弄一个.记录如何将公共组件通过install的方式,注册为全局的组件使用. components目录下,新建bacttop文件夹,内部包含一个index.js文件和一个src文件夹.src文件夹内放backtop.vue组件文件. |--components   |--index.

  • Vue开发Sort组件代码详解

    目录 <template> <ul class="container"> <li v-for="(item,index) in datalist" :key="index"> {{item.text}}<span></span> </li> </ul> </template> <script> export default{ props:{

  • vue实现自定义公共组件及提取公共的方法

    目录 自定义公共组件及提取公共的方法 vue自定义公共组件 vue 提取公共的方法 vue定义公用方法 自定义公共组件及提取公共的方法 vue自定义公共组件 我们在编写页面的时候,会存在公共的组件,比如头部和底部菜单 我们拿公共头部为例子,想在每个页面都显示公共头部的实现方式有两种: 在src/components目录创建目录 common, 再创建header.vue header.vue <template>   <div>   <h1>header in here

  • Vue拖拽组件开发实例详解

    为什么选择Vue? 主要原因:对于前端开发来说,兼容性是我们必须要考虑的问题之一.我们的项目不需要兼容低版本浏览器.项目本身也是一个数据驱动型的.加之,Vue本身具有以下主要特性: •使用虚拟DOM: •轻量级框架: •高效的数据绑定: •灵活的组件系统: •完整的开发生态链. 这就是我们为什么选择Vue框架的一些原因. 为什么要封装成一个Vue组件? 主要目的是可提高代码的复用性和可维护性. •复用性:组件化后,一些样式和逻辑均通过配置参数的方式去差异化体现,所以参数的可配置性提高了组件的复用

  • vue elementui 实现搜索栏公共组件封装的实例代码

    1.背景 vue后台管理系统,会有很多表格页面,表格上方会有一些搜索选项,表格直接使用el-table即可,而搜索栏区域每次写起来都很繁琐,而且多人开发情况下每个人写的样式都不相同,布局样式无法统一. 所以要考虑对搜索栏做一个封装,统一配置引用,提升开发维护效率和界面统一. 完成后的效果大概就是长这样: 2.分析 项目使用的是elementui框架,搜索栏这种表单提交,首先要使用el-form组件来封装,而复杂点就是表单项可能有很多种,例如input输入框.select选择框.日期时间选择框.日

  • 解决vue项目中某一页面不想引用公共组件app.vue的问题

    Vue 单页面应用 把公共组件放在 app.vue 但是我希望某个页面没有这些公共组件怎么办(比如登陆页面)每个页面都有 导航栏 但是我希望 登陆页面只有一个背景色和一个登陆框 没有导航栏 那应该怎样设置呢? vue中文文档:点击进入 在根组件中:在导航栏使用v-show判断当前路由是否是不需要的组件来完成页面: <template> <div id="app"> <home-header v-show="!(path ==='/') "

  • .html页面引入vue并使用公共组件方式

    目录 .html页面引入vue并使用公共组件 问题描述 解决办法 目录结构 vue公共组件框架搭建 步骤详述 总结 .html页面引入vue并使用公共组件 问题描述 整体项目采用传统 .html 文件搭建,vue仅作为渲染数据工具使用,需要使用的地方使用 <script> 标签引入. 现有数个页面,每个页面都包含相同 header 和 footer ,希望可以把 header 和 footer 提取出来,避免太多重复代码. 解决办法 公共部分写在 .js 文件里,本质就是在当前页面中写的公共组

  • vue.js表格组件开发的实例详解

    前言 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 组件开发的基础 组件可以扩展 HTML 元素,封装可重用的代码.我理解为功能模块的模板吧. 对于vue来说,组件是这个样子的,我们在html里面写 <div id="example"> <my-compone

随机推荐