先看效果

由于每次修改element的弹窗样式颜色觉得麻烦,于是就想着自己搞一个,想怎么玩就怎么玩,开干,走起

  • 1、首先创建div
  • 2、给div添加内容
  • 3、把div放入页面中显示
  • 4、添加样式
  • 5、添加事件
  • 6、完成移除添加的div

一、如何创建div,使用document.createElement

    const div = document.createElement("div");div.innerHTML = `<div >测试</div>`

二、创建完后怎么把div加入到页面中,所谓的页面是什么,要么是document.body,要么是你想让他显示到某个元素的中

这里我就直接显示在body中去,首先得判断dom元素的position是否是relative,这里用到了window中的getComputedStyle来进行判断

    let container = document.bodyif (getComputedStyle(container).position === 'static') {container.style.position = "relative";}//将div加入到容器中container.appendChild(div);

三、样式添加 由于使用的是CSS Modules,不是正常的使用,css文件相当于一个对象,导出css文件,然后在去获取

    import messageBox from "./messageBox.module.css"div.innerHTML = `<div class="${messageBox.messageBoxTip}">测试</div><div class="${messageBox.messageBoxTitle}">测试</div>`div.className = `${messageBox.messageBoxContainer}`;

这里得注意,如果使用了css3想要添加动画比如给div的opacity从0到1的过渡,

如果你直接加它是不会有过渡的,由于浏览器渲染是异步的,他不可能执行到上面就直接渲染了,他要等我们代码执行完后才渲染,所以最终显示的opacity的值就是下面设置的1

如果想要有动画效果,就得强制渲染,你只要读取该元素的位置,尺寸等就会导致重新渲染(reflow重排)

在添加到容器中后立马要强制渲染 div.clientHeight;

四:如果有按钮进行点击事件直接使用id,getElementById来获取该元素

    <div class="${messageBox.messageBoxBtn}"><div id="cancelBox" class="${messageBox.boxBtn}">${options.cancelButtonText}</div><div id="confirmBox" class="${messageBox.boxBtn}">${options.confirmButtonText}</div></div>cancelBtn.onclick = () => {}confirmBtn.onclick = () => {}

五:事情做完了就得把div移除,不然还会在中间显示只是看不到而已

div.remove();

补充:添加组件

如果想要在div中加入图标,你可以使用图片,但如果你之前已经写好了一个图标组件,那该怎么把这个组件添加进去呢?

假设有个图标组件:导入组件 import Icon from '/components/Icon'

1、首先html中不可能直接使用组件Icon,我们得把组件转换从html元素

2、如何转换,这里我们就得使用vue 的render函数 在使用前得先导入vue

    import Vue from "vue";function getComponentRootDom(comp, props) {const vm = new Vue({render: h => h(comp, {props})})vm.$mount();return vm.$el;}
参数 1、comp 需传入组件,2、props 组件需要的参数
返回 最终返回的是该组件渲染后的dom树

3、然后就可以在div中加入,然后就可以显示图标了然后在给div添加样式就行了

    const icon=getComponentRootDom(Icon,type)div.innerHTML = `<div>${icon}</div>`

完整代码 在js中返回一个promise是为了点击按钮有后可以续操作

文件目录

  • 弹窗 messageBox.js

      //这里引入图标组件,我这没有暂时不需要// import Icon from '/components/Icon'import messageBox from "./messageBox.module.css"/*** 弹出框* @param content 弹窗的内容显示* @param tip 弹出的标题信息* @param options 显示按钮的文字信息* @returns {Promise<unknown>}*  {HTMLElement} container 容器 消息会显示到该容器的正中间,如果不传,就直接显示页面正中间*/export default function (content = '', tip = '提示', options = {confirmButtonText: '确认', cancelButtonText: '取消'}) {return new Promise((resolve, reject) => {//创建消息元素const div = document.createElement("div");div.innerHTML = `<div class="${messageBox.messageBoxTip}">${tip}</div><div class="${messageBox.messageBoxTitle}">${content}</div><div class="${messageBox.messageBoxBtn}"><div id="cancelBox" class="${messageBox.boxBtn}">${options.cancelButtonText}</div><div id="confirmBox" class="${messageBox.boxBtn}">${options.confirmButtonText}</div></div>`//设置div样式div.className = `${messageBox.messageBoxContainer}`;//默认在页面中间,想要自定义可以作为参数传入containerlet container = document.bodyif (getComputedStyle(container).position === 'static') {container.style.position = "relative";}//将div加入到容器中container.appendChild(div);//由于浏览器渲染是异步的,他不可能执行到上面就直接渲染了,他要等我们代码执行完后才渲染,所以最终显示的opacity的值就是下面设置的1// 如果想要有动画效果,就得强制渲染,你只要读取该元素的位置,尺寸等就会导致重新渲染(reflow重排)div.clientHeight;//回归到正常位置div.style.opacity = 1;div.style.transform = `translate(-50%,-50%)`;const cancelBtn = document.getElementById('cancelBox');const confirmBtn = document.getElementById('confirmBox');//取消按钮的点击事件cancelBtn.onclick = () => {div.style.opacity = 0;div.style.transform = `translate(-50%,-50%) translateY(-25px)`;//虽然消失了但是元素还在,还得把元素移除,监听动画移除事件(该事件只触发一次)div.addEventListener('transitionend', () => {div.remove();reject();}, {once: true})}//确认按钮的点击事件confirmBtn.onclick = () => {div.style.opacity = 0;div.style.transform = `translate(-50%,-50%) translateY(-25px)`;//虽然消失了但是元素还在,还得把元素移除,监听动画移除事件(该事件只触发一次)div.addEventListener('transitionend', () => {div.remove();resolve();}, {once: true})}})}/*** 获取某个组件渲染的dom* @param comp 组件* @param props 组件需要的参数* @returns {Element}*/import Vue from "vue";function getComponentRootDom(comp, props) {const vm = new Vue({render: h => h(comp, {props})})vm.$mount();return vm.$el;}
    
  • 弹窗的css messageBox.module.css

      /*大盒子样式*/.messageBoxContainer {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);z-index: 9999;box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.5);padding: 10px 20px;width: 300px;height: 150px;display: flex;flex-direction: column;align-items: center;justify-content: space-around;border-radius: 8px;color: #000;transition: 0.4s;transform: translate(-50%, -50%) translateY(25px);white-space: nowrap;background: #fff;}.messageBoxTip {width: 100%;height: 20px;line-height: 20px;text-align: left;}.messageBoxTitle {width: 100%;height: 30px;line-height: 30px;padding-left: 4%;box-sizing: border-box;}.messageBoxBtn {width: 100%;display: flex;justify-content: flex-end;align-items: center;}.boxBtn {text-align: center;position: relative;width: 50px;height: 30px;line-height: 30px;font-size: 16px;margin: 0 4%;cursor: pointer;}.boxBtn:hover {background: #21ebff;color: #111;transition-delay: 0.5s;}.boxBtn:nth-child(1) {filter: hue-rotate(270deg);}.boxBtn:nth-child(2) {filter: hue-rotate(90deg);}.boxBtn::before {content: '';position: absolute;top: 0;left: 0;width: 10px;height: 10px;border-top: 2px solid #21ebff;border-left: 2px solid #21ebff;transition: 0.5s;transition-delay: 0.5s;}.boxBtn:hover::before {width: 100%;height: 100%;transition-delay: 0s;}.boxBtn::after {content: '';position: absolute;right: 0;bottom: 0;width: 10px;height: 10px;border-bottom: 2px solid #21ebff;border-right: 2px solid #21ebff;transition: 0.5s;transition-delay: 0.5s;}.boxBtn:hover::after {width: 100%;height: 100%;transition-delay: 0s;}
    
  • 消息js myMessage.js

      //这里引入图标组件,我这没有暂时不需要// import Icon from '/components/Icon'import messageStyle from "./myMessage.module.css"/*** 弹出消息* {string} content 消息内容* {string} type 消息类型 info danger success, warning* {Number} duration 多久消失, 0为不消失* {HTMLElement} container 容器 消息会显示到该容器的正中间,如果不传,就直接显示页面正中间*/export default function (content='成功',options = {}) {const type = options.type || 'success';const duration = options.duration || 2000;const container = options.container || document.body;//创建消息元素const div = document.createElement("div");//如果想要放图标得导入图标组件,必须先得到图标的dom元素,这里传入type类型显示不同的图标let Icon = null;//由于我这里没有这个图标组件就不显示了if (Icon) {const iconDom = getComponentRootDom(Icon, {type});// div.innerHTML=`<span>这里如果想要放图标dom</span><div>这里显示你要展示的内容</div>`div.innerHTML = `<span>${iconDom.outerHTML}</span><div>${content}</div>`} else {div.innerHTML = `<span>${content}</span>`}//设置div样式div.className = `${messageStyle.myMessage} ${messageStyle["myMessage-" + type]}`;//将div加入到容器中//容器的position是否改动过if (getComputedStyle(container).position === 'static') {container.style.position = "relative";}container.appendChild(div);//由于浏览器渲染是异步的,他不可能执行到上面就直接渲染了,他要等我们代码执行完后才渲染,所以最终显示的opacity的值就是下面设置的1// 如果想要有动画效果,就得强制渲染,你只要读取该元素的位置,尺寸等就会导致重新渲染(reflow重排)div.clientHeight;//回归到正常位置div.style.opacity = 1;div.style.transform = `translate(-50%,-50%)`;//等一段时间消失setTimeout(() => {div.style.opacity = 0;div.style.transform = `translate(-50%,-50%) translateY(-25px)`;//虽然消失了但是元素还在,还得把元素移除,监听动画移除事件(该事件只触发一次)div.addEventListener('transitionend', () => {div.remove();//运行回调函数 消失之后去做一些事情options.callback && options.callback()}, {once: true})}, duration)}/*** 获取某个组件渲染的dom* @param comp* @param props* @returns {Element}*/import Vue from "vue";function getComponentRootDom(comp, props) {const vm = new Vue({render: h => h(comp, {props})})vm.$mount();return vm.$el;}
    
  • 消息的css myMessage.module.css

      .myMessage {position: absolute;left: 50%;top: 6%;transform: translate(-50%, -50%);z-index: 9999;box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.5);padding: 10px 20px;line-height: 2;display: flex;min-width: 100px;align-items: center;justify-content: center;border-radius: 8px;color: #fff;transition: 0.4s;transform: translate(-50%, -50%) translateY(25px);white-space: nowrap;}/*默认消息颜色*/.myMessage-info {background: #909399;}/*成功消息颜色*/.myMessage-success {background: #67C23A}/*警告消息颜色*/.myMessage-warn {background: #E6A23C;}/*危险消息颜色*/.myMessage-danger {background: #F56C6C;}
    

到这里代码已经完结,那么怎么用呢,测试的话可以在vue项目的main.js中导入使用就行了

    import myMessage from "./utils/myMessage/myMessage";import myMessageBox from "./utils/messageBox/messageBox";myMessageBox('是否进行删除').then(()=>{console.log("确认");myMessage('删除成功')}).catch(()=>{myMessage('已取消')console.log('取消')});

如果想要在整个vue实例中使用这个方法就可以把方法挂到vue实例中去,然后用this.$XX就可以了

import myMessage from "./utils/myMessage/myMessage";
import myMessageBox from "./utils/messageBox/messageBox";
Vue.prototype.$myMessage=myMessage;
Vue.prototype.$myMessageBox=myMessageBox;
//在vue 页面中使用
this.$myMessageBox('是否进行删除').then(()=>{console.log("确认");this.$myMessage('删除成功')}).catch(()=>{this.$myMessage('已取消')console.log('取消')});

在这里提示一下在vue的prototype原型上加属性和方法都会默认在名字前面添加$符号,在vue的原型上添加属性或方法后就可以在项目的任何组件中使用这些方法和属性,

那为什么要加$符号呢,比如:你在原型中定一个方法叫say,但是没有加$符号去区分,而在组件的data中也定义了一个相同的say的数据,

当在这个页面去使用的时候,你本来是想调用你在原型上定义的方法,结果打印this.say发现是data里面的值而不是方法,

所以这就是为什么最好要加上$的原因,为了区分防止被覆盖了

感谢各位大佬的观看,如有问题请大佬指点

纯js手写一个element的弹窗,方便修改自己想要的样式相关推荐

  1. [js] 手写一个trim()的方法

    [js] 手写一个trim()的方法 function trim(str) { if (str[0] === ' ' && str[str.length - 1] === ' ') { ...

  2. 用 Node.js 手写一个 DNS 服务器

    DNS 是实现域名到 IP 转换的网络协议,当访问网页的时候,浏览器首先会通过 DNS 协议把域名转换为 IP,然后再向这个 IP 发送 HTTP 请求. DNS 是我们整天在用的协议,不知道大家是否 ...

  3. 手写一个简易bundler打包工具带你了解Webpack原理

    用原生js手写一个简易的打包工具bundler

  4. 使用Node.js手撸一个建静态Web服务器,内部CV指南

    文章里有全部代码,也可以积分下载 操作步骤如上图 文章结束 话说这个键盘真漂亮~~ 文章目录 使用Node.js手撸一个建静态Web服务器 一.动静态服务器的概念 1.1 静态Web服务器概念 1.2 ...

  5. 一文帮你搞定90%的JS手写题

    还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题.在工作中还可以对常用的需求进行手写实现,比如深拷贝.防抖节流等可以直接用于往后的项目中,提高项目开发效率.不说废话了,下 ...

  6. 【面试】970- 一文帮你搞定90%的JS手写题

    还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题.在工作中还可以对常用的需求进行手写实现,比如深拷贝.防抖节流等可以直接用于往后的项目中,提高项目开发效率.不说废话了,下 ...

  7. ES6 手写一个“辨色”小游戏

    1. 前言 依稀记得几年前朋友圈流行的辨色小游戏,找出颜色不同的矩形.前些天突发奇想,打算自己手写一个类似的游戏,话不多说,先上 Demo . --项目源码 本实例基于 ES6 实现,并兼容 ie9及 ...

  8. 俄罗斯小方块游戏html,通过h5的canvas手写一个俄罗斯方块小游戏

    开始自己手写一个好玩的俄罗斯方块吧,上变形,左右移动,下加速,空格瞬移等功能,无聊的时候学习下canvas,f12 修改分数,体验金手指的快乐吧 1.定义界面,和按钮 上 下 左 右 2.js部分 1 ...

  9. vue 使用fs_模仿vue-cli,手写一个脚手架

    vue-cli 在vue的开发的过程中,经常会使用到vue-cli脚手架工具去生成一个项目.在终端运行命令vue create hello-world后,就会有许多自动的脚本运行. 为什么会这样运行呢 ...

  10. 未能加载文件或程序集或它的某一个依赖项_手写一个miniwebpack

    前言 之前好友希望能介绍一下 webapck 相关的内容,所以最近花费了两个多月的准备,终于完成了 webapck 系列,它包括一下几部分: webapck 系列一:手写一个 JavaScript 打 ...

最新文章

  1. 项目管理 管理的是什么?
  2. Promise的基本使用
  3. java numa_Java只使用2个CPU中的1个和NUMA(Neo4J)
  4. 方便好用的接口协作工具
  5. Windows系统利用5次shift维权漏洞复现
  6. 从零开始用python处理excel视频_从零开始学数据分析,什么程度可以找工作,如何计划学习方案?...
  7. centos8 开启ftp服务
  8. 【模型转换】最少点的覆盖区间
  9. ITIL好看不好吃?(二)
  10. corpus iweb_智能网络语料库iWeb及其在英语教学中的应用
  11. 一个指导人机系统评估的框架
  12. dcdc芯片效率不高的原因_影响DC-DC转换器效率的主要因素
  13. 计算机不联网会有ip地址吗,不联网的电脑有ip地址吗
  14. ASP.NET Core 导出Excel文件
  15. anbox 使用情况_Anbox 实现分析 2:I/O 模型
  16. 太平洋电信首批通过SD-WAN Ready 2.0服务认证
  17. RUA!ERROR!
  18. Blast中文手册(3)
  19. 计算机网络中的IP到底是什么?
  20. 无胁科技-TVD每日漏洞情报-2022-11-24

热门文章

  1. Excel 培训笔记
  2. 原来TOGAF标准第10版是个活力生态圈
  3. 微信小程序——聊天小程序(从搭建到结束)
  4. 莫烦Python机器学习
  5. 威纶通定时循环操作宏_武器化excel4.0宏演化过程
  6. html动画转换为桌面动态壁纸,怎么设置电脑动态壁纸-动态桌面,这个功能太好玩了...
  7. 用Python弹奏周董的《菊花台》是什么效果
  8. java 企业微信对接_Java对接企业微信
  9. 如何在手机上快速制作小一寸证件照
  10. javascript前端导出Excel简单写法