这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
在使用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
<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> {{ fileName }} {{ fileSize }}关 闭
data中的自定数据的就相当于使用api传入的参数,当我们保存实例后,可以修改这个实例内的data,来达成实时更新的效果
多个实例使用案例参考
<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>显示实例1 增加进度 显示实例1 增加进度 显示实例1 增加进度
本文转载于:
https://juejin.cn/post/7243725204002209852
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
标签:
-
记录--封装一个通过js调用的全局vue组件
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言在
-
法律不惯着要求员工分摊电费
就该让“霸道总裁”的“霸凌”行为碰上“司法钉子”。▲公司办公概
-
买了房子签了合同想退房怎么办 焦点观察
根据规定,买房是需要签订合同的,如果签订房屋买卖合同之后,想要退房
-
成都环球博纳诉刘德华等涉嫌抄袭案二审,原告方当庭表示不同意调解|当前资讯
成都环球博纳诉刘德华等涉嫌抄袭案二审 【成都环球博纳诉刘德华等十被
-
焦点消息!幽默笑话故事_幽默笑话故事大全
1、展开1全部- 学校的男女厕所相连。2、一女生去厕所忘记带卫生纸,
-
dnf二级密码解除网站是什么_dnf二级密码解除网站
1、上官网。2、直接用身份证号解除最直接。本文到此分享完毕,希望对大
-
天天热消息:京雄高速京雄大桥今日合龙 大桥主体完工
今天(6月17日),京雄高速京雄大桥实现合龙,标志着大桥主体完工。作为
-
全球头条:和胜股份:公司是宁德时代电池托盘供应商之一
和胜股份在互动平台表示,公司作为宁德时代电池托盘的供应商之一,双方
-
【天天新视野】怎样做微商赚钱 学生_怎样做微商赚钱
1、懂微信业务:俗话说,未雨绸缪。在做微信业务之前,你需要了解什么
-
债务炸弹“引线”暂除 万亿“新债”引发担忧 病根未除,美债危机还在继续(环球热点)
刚刚在债务上限危机中惊险“过关”,美国又在酝酿新一轮举债。据美
-
世界关注:长江师范学院是几本院校_长江师范学院是几本
1、是二本院校。2、长江师范学院位于长江与乌江交汇处,素有“乌江门户
-
6月上海车牌拍卖将于24日举行 警示价91500元_快资讯
证券时报网讯,上海国拍公司6月17日发布,6月份车牌拍卖将于6月24日(1
-
头条焦点:RJ谈16年夺冠后宣布回归:我喝多了 而且当时勇士还没签杜兰特
RJ谈16年夺冠后宣布回归:我喝多了而且当时勇士还没签杜兰特,勇士,美国
-
世界观天下!“千万工程”调研行丨这里的农民生活为何如此惬意?
早晨,沿着亲水栈道晨跑;午间,在村里的“不晚”咖啡馆点杯咖啡、看看
-
破解世纪难题!“中国造”海水直接制氢,颠覆还是夸大? 焦点
破解世纪难题!“中国造”海水直接制氢,颠覆还是夸大?,氢能,世纪,氢
-
哪条地铁覆盖居住人口规模最多?哪条公交线路换乘能力最强?快来看这份《上海MaaS公共出行年报》_每日信息
上海市绿色出行一体化平台“随申行”与第一财经·新一线城市研究所今天
-
南方聪元债券型发起式 证券投资基金A类份额分红公告
证券投资基金A类份额分红公告(1)自2023年6月17日起,本基金管理人将
-
美式足球规则一分钟看懂 美式足球规则
1、规则:进攻方未能获得新的首功——换句话说,在四次进攻内都未能推
-
从“烧鞋”到“烧钱”,奥康能否靠运动皮鞋“翻身”? 天天新消息
(题图)文|螳螂观察作者|青月年轻人,似乎不再乐意为皮鞋买单。在知乎
-
酱香炒鱿鱼、白菜狮子头、清炖牛肉汤,三道美味营养家常菜
今天介绍三道美味营养的家常菜给大家,这三道家常菜分别是酱香炒鱿鱼、
-
手写板安装后无法写字(手写板安装)|新消息
来为大家解答以上问题,手写板安装后无法写字,手写板安装很多人还不知
-
氢氧化锰沉淀的颜色_氢氧化锰
1、化学式:MnO(OH)制取:由锌锰干电池反应得到:正极反应式:2MnO2+2e-
-
股票行情快报:莱绅通灵(603900)6月16日主力资金净卖出45.30万元
截至2023年6月16日收盘,莱绅通灵(603900)报收于6 29元,下跌0 32%,换
-
全球快讯:改进的意思和用法_改进的意思
1、质量改进的步骤本身是一个PDCA循环,即计划(Plan),实施(Do),检查(Che
-
如何舍弃3.0TV6?坦克500燃油版和混动版怎么选?|环球新消息
长城最近推出新车的速度是非常快的,最近热度很高的坦克500Hi4T车型也
-
优美短句关于励志生活_励志抒情句子|今日热讯
人生就像爬坡,要一步一步来。世界会向那些有目标和远见的人让路。低调
-
维持超宽松!日本央行按兵不动 植田和男:低利率对股市有利
6月16日,日本央行发布最新的货币政策声明。声明表示,央行将基准利率
-
预计年产值一亿五千万!西秀区共享电单车企业投产
6月14日,走进贵州优猴出行科技有限公司在西秀经开区标准化厂房内,工
-
偏远山村的“带货员”
两年前,周应宏被派到云南省普洱市思茅区云仙乡芦山村支援乡村振兴工作
-
世界简讯:鲍健_关于鲍健简述
小伙伴们,你们好,今天小夏来聊聊一篇关于鲍健,关于鲍健简述的文章,