私人定制(附源码):弹出框统一样式一个JS文件就可以解决!

前言

毋庸置疑,现在的CP经理对于浏览器自带的弹出框已经产生审美疲劳。

在这里为什么我会强调CP经理呢?因为下面的陈述句可能就是你我都日常:

…我认为这个需求可以实现

…哦?这个效果实现不了吗?

…那个太难看了,咱能不能自己做个?

…现在我就是用户!!!

注:CP经理——传说中一种可怕的怪物,对于程序猿有望而生畏的核弹级杀伤力!

是故,

为了守护世界的和平!

为了防止世界被破坏!!

为了不再996!!!

为了面前的诸位小可爱们不再承受可怕的定制化弹出框的迫害!

我!一名茫茫苦海屌丝程序员!决定亲自手把手教你精准、快速、高效的完成属于自己的、个性化的弹出框设计方案!

目录

效果图

仿prompt

仿prompt

仿alert

仿alert

仿confirm

仿confirm

基本样式

基本样式

源码地址

Github地址: https://github.com/ming131419/pxu

JS源码地址https://github.com/ming131419/pxu/blob/dev/index.js

压缩JS地址https://github.com/ming131419/pxu/blob/dev/dist/index.js

项目主要文件释义:

pxu:
	- index.html	// 示例html
	- index.js	// 主文件,闭包封装pxu(Personal Window)

由于master分支主要提供npm组件包,所以如果您想拥有属于自己的可定制化的pxu,我建议您在devclone/fork哦!

操作步骤

第一步、引入依赖

目前提供两种方式引入。

  • 通过npm install pxu安装
  • 通过下载/复制js导入,可通过上面github链接进行复制

注意

如果您的项目是Node并且使用Vue等框架,建议您通过npm install pxu方式安装;

如果您的项目以原生JS开发为主,建议您直接复制链接JS内容进行使用

如果您的项目既使用了Vue等框架,并且也有原生JS开发部分,那也可以直接引入JS文件使用呦!

其实我之所以要写这个插件,主要还是为了解决我现在所在项目中所遇到的问题——我们项目分为两部分,一部分作为后端和官网首页,这一部分的页面按主要使用Nunjucks组件模板;另一部分主要作为后台管理,使用Vue组件模板。

第二步、使用方式

// pxu($1, $2, $3, $4, $5)
// $1 : 表示弹出框的icon图标类型,目前仅提供warning\success\shutdown\restart四种icon
// $2 : 表示弹出框的的标题,可以是html字符串
// $3 : 表示弹窗的主要内容描述对象,可以是html字符串。
//      注意:如果html字符串中包含input,那么该标签中必须要包含id为pxu的属性,否则关闭弹出框获取不到确认数据,
//      示例:<input id="pxu" type="text" placeholder="请输入登录密码" style="..." />
// $4 : 表示弹出框的取消按钮
// $5 : 表示弹出框的确认按钮,必填项,默认为“确定”
 pxu('warning',                                // 可为null
    '您确认继续重启吗?',                        // 可为null
    '请确保您的信息填写正确后,提交后无法修改',     // 可为null
    '取消',                                     // 可为null
    '立即前往').then(res => {
   console.log(res)
 });

仿prompt样式代码

pxu(null,
  '安全校验',
  '<input id="pxu" type="text" placeholder="请输入登录密码" />',
  '取消',
  '确定').then(res => {
  console.log(res)
});
仿prompt

仿alert样式代码

pxu('warning',
  null,
  'Please make sure that your information is filled in correctly and cannot be modified after submission?',
  null,
  '确定').then(res => {
  console.log(res)
});
仿alert

仿confirm样式代码

pxu('success',
  null,
  '您的操作存在风险,是否继续?',
  '取消',
  '确定').then(res => {
  console.log(res)
});
仿confirm

基本样式样式代码

pxu('restart',
  '是否重启',
  '您的操作存在风险,是否继续?',
  '取消',
  '确定').then(res => {
  console.log(res)
});
基本样式

源码分析(高级)

该插件采用常见的闭包方式进行分装,对外仅爆露pxu函数

window.pxu = (function (win, doc) {
	...
    return async function (type, title, des, btnCancel, btnEnsure) {
      type = type || ''; // window type. At present, only support warning\success\shutdown\restart
      title = title || ''; // pop title
      des = des || ''; // confirm info
      btnCancel = btnCancel || ''; // cancel button info
      btnEnsure = btnEnsure || '确定'; // ensure button info
      return await personalWindow({
        type: type,
        title: title,
        des: des,
        btnCancel: btnCancel,
        btnEnsure: btnEnsure
      })
  }
})(window, document);

出于练习目的,模仿jq封装了下$函数,代码实现也很简单,通过querySelector实现:

  let $ = function (selector) {
    // let t = selector.trim().substring(0, 1);
    // let el = selector.trim().substring(1, Infinity);
    // let type = {
    //   '.': function (el) {
    //     return doc.getElementsByClassName(el);
    //   },
    //   '#': function (el) {
    //     return doc.getElementById(el);
    //   }
    // };
    return doc.querySelector(selector) || null
  };

为了方便后续扩展,通过JSON对象方式封装了html标签的创建,要注意的_html$对象中的顺序关乎html中标签创建的顺序,不建议随便更改。对象中key表示标签的唯一标识,后者表示要创建的标签类型:

self._html$ = {
  popLayer: 'div',
  popBox: {
    closeIcon: 'div',
    type: 'div',
    title: 'div',
    des: 'div',
    btnBox: {
      btnCancel: 'button',
      btnEnsure: 'button'
    }
  }
};

self._box$ = personalWindow.createBox(self._html$, doc.getElementsByTagName("body")[0]);

personalWindow.createBox = function (html, parent) {
    let res = {};
    let deepCreate = function (obj, parent) {
      if (!obj) return;
      for (let _k in obj) {
        if (typeof obj[_k] === "object") {
          res[_k] = personalWindow.createTag(parent, 'div', personalWindow.camel2underline(_k))
          deepCreate(obj[_k], res[_k]);
        } else {
          res[_k] = personalWindow.createTag(parent, obj[_k], personalWindow.camel2underline(_k));
        }
      }
      return res
    };
    return deepCreate(html, parent);
  };

插件中的css样式也是通过JSON对象封装处理的:

personalWindow.existOf(self, 'btnCancel', {
  "padding": "6px 41px",
  "border": "1px solid var(--btn-color)",
  "border-radius": "5px",
  "cursor": "pointer",
  "outline": "none",
  "margin-right": "30px",
  "background-color": "var(--default-bg-color)",
  "flex": "auto"
}); // CSS 对象通过封装的this.obj2css

personalWindow.existOf = function (self, item, style, obj) {
  let option = self._options$,
    box = self._box$;
  console.log(`box[item]: `, box[item]);
  if (item && option[item]) {
    box[item].innerHTML = obj || option[item];
    this.appendStyle({
      [box[item]['class']]: style
    })
  } else {
    box[item].remove();
  }
};

personalWindow.appendStyle = function (style) {
  this._style$.innerText += this.obj2css(style)
};
// 只是通过简单的字符替换进行转化的
personalWindow.obj2css = function (obj) {
  return JSON.stringify(obj).trim()
    .replace(/^\{|\"|\}$/g, '')
    .replace(/\,/g, ';')
    .replace(/\}/g, ';}')
    .replace(/\:\{/g, '{')
    .replace(/\}\;/g, '}')
    .replace(/DOT/gi, ',');
};

除以上比较核心的几个点外,插件里面还分装了需要用的方法,比如将驼峰命名变量转化成下划线命名等。

其他的话

1、插件里面icon主要使用svg格式,如果您想定制属于的自己的icon图标,我建议您也通过这种方式哦!

图片转换可参考:jpg,png图片在线转svg

2、要注意的是插件里面的css样式采用的是flex布局,如果您欠缺这方面的知识,可参考阮一峰老师的Flex 布局教程:语法篇

3、目前,该插件不支持动画弹出效果,至于要不要做这个效果,还要看小伙伴在评论区留言呀!如果您对该插件有更好的意见或建议欢迎在github上提issure或者评论区留言!

4、如果本篇恰好get到了你的点,而您恰好又对私人定制化更加感兴趣——想要做出适用于自己项目所需要的弹出框及样式,那么我会详写一篇关于pxu二次开发的文章呦

5、小博主正式接触前端不到半年,大佬们看到源码可能感觉比较low,有改进的地方希望大佬能够指出!

TIP

这篇文章完成于1024的前一天,本来打算1024发布的,但出于npm插件管理不熟悉的缘故导致拖延到今天!如果大家感兴趣的话,我也会写一篇关于npm上发布组件的文章呢!

最后的最后,感兴趣的小伙伴希望可以点个赞哦!如果您有使用的意向,小树更希望您能在github上给个start呀!

愿看到最后的小可爱们开心快乐每一天!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值