npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@allo_shuang/modal

v1.0.9

Published

统一弹窗组件。用于规范项目弹窗管理的架构及使用。减少手动操作及心智成本。UI组件库使用Element-UI。

Downloads

40

Readme

弹窗组件

一. 背景及用途

  • 当前问题:

    • 工程组织问题:

      • 项目中弹窗文件分布于各个业务代码中,很难实现复用,引用路径复杂。
      • 各弹窗的显隐控制逻辑混杂在业务代码中,各种业务props传递复杂
      • 父组件被隐藏时,弹窗也会被隐藏
    • 前端效率问题:

      针对弹窗这种可能一辈子也不会展示的组件:

      • ElementUI默认底层使用v-show实现,依然会绘制到dom树中
      • 理论上应该使用动态加载,不使用,不加载。减小最后打包的大小
    • 心智成本:

      • 个人风格及经验千差万别
      • 弹窗公共逻辑重复编写,且容易出错。
      • 新人接手旧项目,难以理解起外部逻辑及传入参数。
  • 本组件主要解决的问题:

    • 工程组织问题:
      • 统一项目中所有弹窗文件位置至单一文件夹管理。
      • 弹窗由统一单独的dom元素负责展示,全自动。
    • 前端效率问题:
      • 使用webpack中require.context省去了手动引入大量弹窗文件的工作,同时默认支持动态加载。用不到的弹窗,永不加载。
      • 考虑到扩展性,提供四种优先级的公共参数配置
      • 提供公共样式,loading状态,确定及取消逻辑,确定/取消按钮的显隐控制等
    • 心智成本:
      • 无需手动引用及注册组件,减少代码量。
      • 所有业务相关参数在一个对象中传入,不用定义大量的props。
      • 显隐逻辑自治,无需手动管理相关逻辑。
      • 单一弹窗,单一逻辑。类似于纯函数,所有逻辑由传入的参数控制,便于不同的业务逻辑复用。
      • 默认提供loading状态,处理异步逻辑时,只用关心业务接口。

二. 安装

1.安装库

npm i @allo_shuang/modal@latest -S

2.在src目录下新建文件夹/modal

3.在main.js文件中引用

import Modal from '@allo_shuang/modal'

Vue.use(Modal,{参数放这里...});

实际项目中,在/modal文件夹中创建index.js文件并在文件中引入了组件库,及自定义的样式文件

/modal

------index.js(在这里引入组件库及Vue.use传递统一配置参数,引入样式文件)

------style.scss

这样在main.js文件中只需引入@/modal即可。将配置及样式统一在modal文件夹中管理

###三. 使用

以新建弹窗ExampleModal为例

  1. 在src/modal文件夹中新建文件夹src/modal/ExampleModal并在其中创建index.vue文件。这个组件为弹窗中间部分显示的内容

  2. index.vue内部定义props:

     props: {params: Object},//params对应3中传入的参数
  3. 在任意想要使用弹窗的地方,调用:

    this.$modal.show('ExampleModal', {组件内部需要的参数放这里,对应2的params})

四. 自定义选项

按照优先级,本组件有四个地方可以配置如下参数:

| 参数名 | 默认值 | 说明 | | ----------------- | ------ | ---------------------------------------- | | title | null | 弹窗标题 | | width | 640px | 宽度 | | cancelText | 取消 | 取消按钮文字,设为空字符串''时,按钮隐藏 | | okText | 确定 | 确定按钮文字,设为空字符串''时,按钮隐藏 | | showFooter | true | 确认/取消按钮所在的footer是否显示 | | closeOnClickModal | false | 同elementUI-Dialog的close-on-click-modal | | showClose | false | 同elementUI-Dialog的show-close | | customClass | ‘’ | 自定义的类名,用于个性化弹窗样式 |

参数优先级:

手动传入 > 组件定义 > 全局定义 > 默认值

  1. 唤起弹窗时传入的参数

    this.$modal.show('ExampleModal', {放这里的参数优先级最高})
  2. 子组件内部定义的参数,与data,methods,生命周期等同级定义的参数

    export default {
        title: '我是标题',<-------这里的优先级第二高
        okText:'提交',<-------这里的优先级第二高
        ...
        ...
        data() {return {}},
        methods:{}
    }
  3. 全局定义的参数。Vue.use传入的参数中:

    Vue.use(Modals, {
    title: '我是标题',<-------这里的优先级第三高
    okText:'提交',<-------这里的优先级第三高
    showFooter:false<-------这里的优先级第三高
    ...
    })
    
  4. 默认值。如表中所列。代码在UniModal.vue中

    
      const defaultParams = {
        title: null,
        width: '640px',
        cancelText: '取消',
        okText: '确定',
        showFooter: true,
        closeOnClickModal: false,
        showClose: true,
        customClass: ''
      }

五. 内置方法

  • 组件methods中

    • 如果定义了onCancel()方法,则会忽略默认的取消关闭操作
    • onOK()为点击确定按钮时触发的方法,需要自己实现
  • 关闭当前弹窗

    this.$modal.close()
  • loading状态:loading状态下显示loading动画,屏蔽弹窗上所有交互操作,确认/取消按钮均不可点击。

    • 常用于点击确定按钮后,发出网络请求。
    this.$emit('updateLoading', true/false)
  • 内置的确认弹窗:

    • this.$modal.text(params,callback):纯文本内容,无图标

    • this.$modal.success(params,callback):绿色✓图标+文本

    • this.$modal.warning(params,callback):黄色!图标+文本

    • this.$modal.error(params,callback):红色x图标+文本

    • this.$modal.info(params,callback):蓝色i图标+文本

    • 上述五个方法的参数:

      • params:除自定义参数与上述内置参数外,额外增加三个参数:

        • content:文本内容
        • elementIcon:elementUI中Icon的名字,例如:'el-icon-warning',
        • iconColor:图标的颜色
      • callback:点击确认的回调。形如(params, closeModal, setLoading) => {}

        • params:与第一个参数params相同,用于回传自定义参数

        • closeModal:关闭弹窗的方法。closeModal()

        • setLoading:控制弹窗的loading状态

//例如,依据companyId删除信息
this.$modal.warning(
	{title:'警告',content:'确认删除公司信息吗?',width:'200px',companyId:'com-oiie-9839'},
  (params, closeModal, setLoading) => {
    setLoading(true)
    api.deleteCompanyInfo(params.companyId).then(()=>{
        setLoading(false)
        closeModal()
      })          
  })
)

六. 样式

除了手动传入的customClass类名外,默认提供类:modal-inner-class

可以在.modal-inner-class类下定义公共样式,在自定义类名下定义弹窗特异样式。

七. Q & A

  • 文件夹是否只能叫/modal?

    • 不是的,如果使用的是vue-cli创建的项目,可以在.env文件中自定义常量:

      VUE_APP_MODAL_PATH = '自定义路径'

      同时在引入组件库时,使用

      import Modals from '@allo_shuang/modal/cli'

      原理:require.context编译时,第一个参数为字符串,不接受变量及运算...

  • 是否只支持Element-UI?

    • 算是吧。因为默认使用的是el-dialog。理论上使用任何UI组件库都是可以的。这个组件最开始是React+AntD版的,现在使用VUE技术栈,顺便迁移过来的。
  • 为什么看网络请求,发现弹窗对应的js文件请求了两次?

    • 这是因为webpack对动态加载的文件做了prefetch以提高性能。
    • 第一个请求可以在header中看到Purpose: prefetch
    • 第二个请求可以看到size一栏目显示:(prefetch cache)
    • 可以在webpack或者vue.config.js中禁用prefetch。这是另外的话题。
  • 既然使用了Element-UI,为什么不直接使用this.$confirm方法而要提供默认的success等方法?

    • 首先是为了将默认的这些方法统一归到默认dom下进行管理
    • 使其支持普通弹窗接受的任何参数,减少心智负担
    • 提供了loading等高级功能
    • 默认的confirm不太支持高级定制
    • 默认方法也是动态加载的,不使用不加载
  • 为什么生成key要使用random方法?

    • 即使是同名的弹窗,也要使用不同的key来保证单个弹窗的独立性
    • 不排除将来同时打开两个同名的弹窗
  • 代码中的overlay参数是干什么的?

    • 你居然发现了隐藏参数!!!
    • 默认同一时间只有一个弹窗存在。如果打开弹窗时,传入overlay:true,则弹窗会同时最在。所以弹窗在容器中使用栈来保存的。同时closeAll方法也是因为同样的原因而存在。
    • 规划中多弹窗的情况有很多功能及场景,预计在后续版本中放出,所以文档中暂时隐藏该参数。
  • 为什么要自己写一个遮罩?

    • 多个弹窗切换时,如果使用element-ui自带的遮罩,会出现闪屏的现象。所以自己实现一个遮罩在最下方,同时默认遮罩全部隐藏。

八. 相关技术点

  • 如何自定义组件,Vue.use()的使用

  • require.context的使用及与动态加载的结合

  • Object.create(null)

  • 实例化单文件组件及单独挂载:new + Vue.extend + .$mount() + document.body.appendChild

  • Vue挂载全局方法,Vue.prototype.xxx=

  • 使用key属性来强制刷新/更新组件

  • 获取动态加载组件内定义的值与方法:

    component().then(module => {
            if (module && module.default) {
            module.default.xxxxxx
    }})
  • 动态组件的使用

  • Vue-cli项目环境变量的规则:在.env文件中以VUE_APP_开头

九. TODO:

  • [ ] 增加element-loading-text,element-loading-spinner,element-loading-background的支持
  • [ ] 多弹窗展示时的遮盖,显隐,参数传递等
  • [ ] 增加默认的样式代码以适配常见场景,例如弹窗中,form的input长度改为100%等