记录--封装一个通过js调用的全局vue组件

news2024/9/20 20:31:51

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言

在使用vue项目编写的时候,不可避免的会碰到需要时js api来调用组件进行显示的情况

例如饿了么element ui 的 Notification 通知、Message 消息提示等组件

虽然已经提供了,但是由于api的限制,我们只能通过特定的参数来有限的改变组件的样式

之前的文章说过可以使用 new Vue()Vue.extends等方法来进行改变这些api组件的样式

但是同时它们也有个缺点,无法自动实时更新数据,也就是没有双向绑定,只能静态布局,为了解决这个痛点

我们自己动手封装一个全局js api调用组件,然后再把需要的数据传过去进去更新,自己动手丰衣足食

就以饿了么element-ui的通知组件Notification为例,实现一个全局通知弹窗下载进度条组件

正文

使用Vue.extend构造器来创建是最为方便的,不过和之前不同的是,这样创建的实例组件只能创建单个,每一次调用都会重新创建一个新的实例,不会对原有的实例进行更新,所以我,我们要对实例进行缓存,以便后续的数据更新

这里我以自定义创建一个下载进度弹窗通知为例

首先我们创建一个组件文件夹下的js文件

/components/DownLoadNotification/index.js

实现思路是用Vue.extend构造组件后,把api接收的参数直接传入组件data使用,并为每个实例生成id,拿出dom插入到全局body中,当生成多个实例时动态计算定位的偏移量避免组件重叠

import Vue from 'vue'
import component from './index.vue'
​
const DownLoadNotification = Vue.extend(component)
​
const instances = [] // 实例缓存列表
​
export const notify = (options) => {
  let instance; // 单个实例
​
  options.onClose = function() { // 把删除当前实例的方法传入组件内
    removeNotify(instance.id)
  }
  options.onCloseAll = () => { // 把删除所有实例的方法传入组件内
    removeNotifyAll()
  }
​
  // 直接控制实例的data,而不是通过propsData传入
  instance = new DownLoadNotification({
    data: options,
  })
  instance.id = Date.now(); // 生成id
  instance.$mount(); // 挂载,生成dom节点
  document.body.appendChild(instance.$el) // 把dom节点添加到body全局
  instance.visible = true // 先挂载节点再显示节点里的内容,可以出现过渡动画,而不是一开始全部显示
​
  // 计算多个实例时的偏移量
  // 第一个不需要计算,把push放到循环下面,数组为空时不会循环,第二次开始则会进行计算
  let verticalOffset = 0
  instances.forEach((item) => {
    verticalOffset += item.$el.offsetHeight + 16 // 每个组件高度间隔16px
  })
​
  verticalOffset += 16 // 首次最下面的组件底部距离最底部也有16px的间隙
​
  instance.verticalOffset = verticalOffset // 计算出来的偏移量赋值到组件中data
​
  instances.push(instance) // 缓存实例
  return instance
}
​
// 删除单个组件实例
function removeNotify(id) {
  const index = instances.findIndex(item => item.id === id)
  index !== -1 && instances.splice(index, 1)
}
​
// 删除所有组件实例
function removeNotifyAll() {
  for (let i = instances.length - 1; i >= 0; i--) {
    instances[i].close(); // 调用组件内的删除方法来同时删除实例和dom
  }
}

删除时既要清空组件dom又要删除实例,所以把在js中定义的删除实例方法传入组件,组件需要删除时调用即可

需要注意的是,当有多个全局组件,删除其中一个时,位置应当发生改变

所以删除其中的一个组件实例时要重新计算偏移量位置

重新改造一下 删除单个组件实例 的方法,大致做法就是,拿到被删除的当前实例的高度,然后从被删除实例的位置开始遍历,后面的实例逐一删除被删除的实例高度和边距

// 删除单个组件实例
function removeNotify(id) {
  let index = -1;
  const len = instances.length; // 未删除前数组总长度
  const instance = instances.filter((instance, i) => { // 获取保存当前删除的实例
    if (instance.id === id) {
      index = i; // 保存索引
      return true;
    }
    return false;
  })[0];
  instances.splice(index, 1); // 删除实例
​
  if (len <= 1) return // 只有一个实例时不需要重新计算位置
  const position = instance.position; // 获取实例定位字段
  const removedHeight = instance.$el.offsetHeight; // 获取实例高度
​
  for (let i = index; i < len - 1 ; i++) { // 从被删除的位置开始遍历
    if (instances[i].position === position) { // 修改的位置定位是否一致
      // 将后续元素的定位位置 减去 上一个删除的元素宽度 + 16px 的首次底部边距
      instances[i].$el.style[instance.verticalProperty] =
        parseInt(instances[i].$el.style[instance.verticalProperty], 10) - removedHeight - 16 + 'px';
    }
  }
}
接下来在编写组件/components/DownLoadNotification/index.vue
<template>
  <el-collapse-transition>
    <div v-if="visible" :class="['DownLoadNotification']" :style="positionStyle">
      <div class="header">
        <span>{{ fileName }}</span>
        <span>{{ fileSize }}</span>
      </div>
      <el-progress
        :percentage="downLoadProgress"
        :status="downStatus"
        :stroke-width="15"
      ></el-progress>
      <el-button @click="close" size="mini">关 闭</el-button>
    </div>
  </el-collapse-transition>
</template>
<script>
export default {
  data() {
    return {
      /* 自定义数据 */
      fileName: "",
      fileSize: "",
      downLoadProgress: 0,
      downStatus: "",
​
      /* 组件基础数据 */
      id: null, // 实例id
      visible: false, // 显示控制按钮
      position: "bottom-left", // 显示方位
      verticalOffset: 0, // 位置偏移量
      onClose: null, // js中传入的删除当前组件方法
      onCloseAll: null, // js中传入的删除所有组件方法
    };
  },
  computed: {
    // 默认纵向布局,定位为 左 或者 右 时边距为10px
    horizontalClass() {
      // 实例左偏移还是右偏移
      return this.position.indexOf("right") > -1 ? "right" : "left";
    },
    verticalProperty() {
      // 实例上还是下
      return /^top-/.test(this.position) ? "top" : "bottom";
    },
    positionStyle() {
      // 多个实例时的偏移量
      return {
        [this.verticalProperty]: `${this.verticalOffset}px`,
      };
    },
  },
  methods: {
    // 销毁当前组件
    close() {
      this.visible = false;
      this.$el.addEventListener("transitionend", this.destroyElement); // 添加事件,在过渡效果结束后再销毁组件
      this.onClose(); // 调用外面js传入组件的方法
    },
    // 销毁所有组件
    closeAll() {
      this.onCloseAll();
    },
    // 销毁组件方法
    destroyElement() {
      this.$el.removeEventListener("transitionend", this.destroyElement);
      this.$destroy(true);
    },
  },
};
</script>
<style lang="less" scoped>
.DownLoadNotification {
  width: 300px;
  height: 60px;
  background-color: #dcdfe6;
  position: fixed;
  border-radius: 10px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  padding: 20px;
  .header {
    color: #606266;
    margin-bottom: 10px;
  }
}
.right {
  right: 10px;
}
.left {
  left: 10px;
}
</style>
​

data中的自定数据的就相当于使用api传入的参数,当我们保存实例后,可以修改这个实例内的data,来达成实时更新的效果

多个实例使用案例参考

<template>
  <div id="app">
    <div class="btn">
      <el-button @click="show(1)">显示实例1</el-button>
      <el-button @click="addBtn(1)">增加进度</el-button>
    </div>
    <div class="btn">
      <el-button @click="show(2)">显示实例1</el-button>
      <el-button @click="addBtn(2)">增加进度</el-button>
    </div>
    <div class="btn">
      <el-button @click="show(3)">显示实例1</el-button>
      <el-button @click="addBtn(3)">增加进度</el-button>
    </div>
  </div>
</template>
<script>
import { notify } from "./components/DownLoadNotification/index.js";
export default {
  name: "App",
  data() {
    return {
      instance1: null,
      instance2: null,
      instance3: null,
    };
  },
  methods: {
    show(index) {
      this[`instance${index}`] = notify({
        fileName: `测试文件${index}.zip`,
        fileSize: "100mb",
        downLoadProgress: 0,
        downStatus: "success",
      })
    },
    addBtn(index) {
      this[`instance${index}`].downLoadProgress += 10
    },
  },
}
</script>
<style lang="less">
#app{
  display: flex;
  align-items: center;
}
.btn{
  display: flex;
  flex-direction: column;
}
</style>

GIF.gif

本文转载于:

https://juejin.cn/post/7243725204002209852

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/660076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

postman和jmete接口测试的用法与区别

目录 前言 接口测试的目的 接口测试怎么测&#xff1a; 1.创建接口用例集&#xff08;没区别&#xff09; 2.步骤的实现&#xff08;有区别&#xff09; 3数据用例的实现 4断言的实现 5执行 6其他 总结&#xff1a; 前言 前阶段做了一个小调查&#xff0c;发现软件测…

DETR 系列有了新发现?DETRs with Hybrid Matching 论文阅读笔记

DETR 系列有了新发现&#xff1f;DETRs with Hybrid Matching 论文阅读笔记 一、Abstract二、引言三、相关工作目标检测中的 DETR其它视觉任务中的 DETR标签赋值 四、方法4.1 基础知识通用的 DETR 框架通用的可变形 Deformable-DETR 框架 4.2 混合匹配4.2.1 混合分支计划一对一…

client-go的Indexer三部曲之三:源码阅读

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 《client-go的Indexer三部曲》全部链接 基本功能性能测试源码阅读 本篇概览 本文是《client-go的Indexer三部曲》系列的终篇&#xff0c;主要任务是阅读和…

Vue全家桶(四):Vue Router 路由

目录 Vue Router1. 相关理解1.1 Vue Router的理解1.2 对SPA应用的理解1.3 路由的理解 2. 基本路由2.1 vue-router使用步骤2.2 几个注意点2.3 触发路由2.4 嵌套路由2.5 路由传递参数方式2.5.1 params 方式2.5.2 Query的方式 2.6 命名路由2.7 路由的props配置2.8 路由跳转的repla…

H3C-HCL模拟器-VLAN划分实验

一、实验拓扑结构图&#xff1a; 二、实验需求&#xff1a; 1. 按图示为PC配置IP地址 2. SW1和SW2上分别创建vlan10和vlan20&#xff0c;要求PC3和PC5属于vlan10&#xff0c;PC4和PV6属于vlan20 3. SW1和SW2相连的接口配置为trunk类型&#xff0c;允许vlan10和vlan20通过 4…

AI工程化的“基座能力”?—— 聊聊GPT Function Calling

点击↑上方↑蓝色“编了个程”关注我~ 这是Yasin的第 94 篇原创文章 最近AI大模型火出了圈&#xff0c;很多人惊叹它的智能程度。但大多数人都以为它的能力主要在“聊天”、“写文案”这方面。然而实际它能做的远远更多。 Chat GPT是当今世界上最智能的模型&#xff0c;它前段时…

【Linux】—— 详解进程PCB和进程状态

前言&#xff1a; 在上篇我们已经对有关体系结构的基本知识进行了详细的介绍&#xff0c;接下来我们将进入网络编程的第一个大块—— 有关进程相关的知识&#xff01;&#xff01;&#xff01; 目录 前言 &#xff08;一&#xff09; 基本概念 1、描述进程-PCB 2、查看进程…

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降 逻辑回归分类Logistic Regression ClassificationLogistic Regression: Log OddsLogistic Regression: Decision BoundaryLikelihood under the Logistic ModelTraining the Logistic ModelGradient Desc…

使用vue脚手架搭建前端工程(附:搭配ElementUI来快速开发)

目录 一、搭建过程 1. 全局安装webpack&#xff08;打包工具&#xff09; 2. 全局安装vue脚手架 3. 初始化vue项目 4. vue项目目录的简单介绍 二、执行流程分析 三、自己造一个组件案例 四、ElementUI的使用 1. 环境的引入 2. 一个简单使用 3. 使用它来快速搭建后台管…

AI绘画Stable diffusion保姆级教程,看这一篇就够了「安装-配置-画图」

随着chat gpt爆火之后&#xff0c;越来越多的人开始关注人工智能&#xff0c;人工智能相关的其他应用如AI绘画&#xff0c;也再次得到人们的关注。AI绘画的确很上头&#xff0c;最近几天小编也研究一下&#xff0c;这里把研究的过程以及中间遇到的问题整理一下&#xff0c;我这…

吴恩达471机器学习入门课程3第1周——异常检测

异常检测 1 导包2 - 异常检测2.1 问题陈述2.2 数据集可视化您的数据 2.3 高斯分布2.2.1 估计高斯分布的参数2.2.2 选择阈值 ϵ \epsilon ϵ2.4 高维数据集异常检测 实现异常情况检测算法&#xff0c;并应用它来检测网络上的故障服务器。 1 导包 import numpy as np import ma…

管理类联考——英语二——知识篇——写作题目说明——B节

MBA&#xff0c;MPA&#xff0c;MPAcc管理类联考英语写作部分由A&#xff0c;B两节组成&#xff0c;主要考查考生的书面表达能力。共2题&#xff0c;25分。A节要求考生根据所给情景写出约100词(标点符号不计算在内)的应用文&#xff0c;包括私人和公务信函、通知、备忘录等。共…

【ESP8266 (12F)】硬件参数 以及 固件烧录

本文资料及工具地址&#xff1a;https://github.com/CQUPTLei/ESP8266 一、基本关系1.1 ESP8266 芯片 和 ESP 12F 模组1.2 乐鑫科技和安信可 二、ESP 8266开发板2.1 ESP 12F 产品规格2.2 ESP8266 开发板 三、固件与固件下载3.1 什么是固件3.2 固件和用户程序3.2 如何下载固件3.…

Linux下配置lunavim

前言 在lunavim官网中提供了安装脚本&#xff0c;一件安装即可&#xff0c;但是经常因为网络不稳定而导致安装失败。这里提供在Linux下进行git加速的几种方法&#xff0c;可以尝试下。如果问题没有解决&#xff0c;也不要担心&#xff0c;我们还提供了两种平替方法进行luanvim的…

linux实验五sed和awk

按要求写出正则表达式 显示/etc/passwd中以bash结尾的行;显示/var/log/secure文件中包含“Failed”或“FAILED”的行查找/etc/man_db.conf中含有“以m开头&#xff0c;并以n结尾的单词”模式的行&#xff1b;显示/etc/man_db.conf中&#xff0c;包含Linux绝对路径的行&#xff…

基础巩固(六)自定义View

文章目录 View绘制流程MeasureLayoutDraw 自定义View的实现的步骤步骤1&#xff1a;实现Measure、Layout、Draw流程自定义 MeasureViewGroup.LayoutParamsMeasureSpec 自定义Layout 自定义属性 绘制工具类Paint具体使用 PathCanvas View绘制流程 在绘制前&#xff0c;系统会有一…

Python恶搞代码

文章目录 前言Tkinter界面设计Threading多线程恶搞代码 尾声 前言 快来领取python无限弹窗恶搞代码吧&#xff01;每天写一些有趣的小程序&#xff0c;带你成为一个浪漫的程序员&#xff01; Tkinter界面设计 1. 创建一个简单的界面 Tkinter 是 Python 标准库中的一个 GUI&…

自然语言处理从入门到应用——动态词向量预训练:双向语言模型

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 对于给定的一段输入文本 w 1 w 2 ⋯ w n w_1w_2\cdots w_n w1​w2​⋯wn​&#xff0c;双向语言模型从前向&#xff08;从左到右&#xff09;和后向&#xff08;从右到左&#xff09;两个方向同时建立语言模型。这样做…

go 调试利器之pprof指标分析

文章目录 概要一、指标类型1.1、堆栈指标1.2、CPU指标分析1.3、http-pprof 二、go tool pprof2.1、可视化2.2、CPU火焰图 概要 Go语言原生支持对于程序运行时重要指标或特征进行分析。pprof是其中一种重要的工具&#xff0c;其不仅可以分析程序运行时的错误&#xff08;内存泄…

ChatGPT 之 LangChain的文本切割方法对比

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; ChatGPT面向对话格式的文本理解很好&#xff0c;但如果要把网络上的文章让ChatGPT直接分析则会有格式的问题。文本清洗是个大课题&#xff0c;讲起来需要很多篇幅&#xff0c;优化起来前路漫…