V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
a62527776a
V2EX  ›  分享创造

开发了一个 vue 的弹窗组件 用于满足日常开发中的弹窗需求

  •  
  •   a62527776a ·
    a62527776a · 2019-11-19 12:01:29 +08:00 · 5179 次点击
    这是一个创建于 1617 天前的主题,其中的信息可能已经有所发展或是发生改变。

    样式复刻 ios 的弹窗
    开发了蛮长一段时间 基本现在都经常用他
    开发的初衷是经常开发一些活动页
    但是页面都是一些比较简单的 不是很想引入 UI 库 但是单独的弹窗仓库都没有太好看的 就自己开发了一个

    因为要支持 script 引入,所以打包了一份 vue-dialog-x.window.js

    支持 5 种弹窗形式 分别是 alert confirm prompt actions dialog

    Coverage Status
    npm type definitions npm

    支持 Promise 的 iOS 样式风格的弹窗提示

    代码样例

    基础

    await this.$dialog.confirm({
      title: '提示',
      message: '请登陆后再试',
      okText: '去登陆'
    })
    
    

    异步 confirm

    async () => {
      await dialogX.confirm({
        message: '点击确认后购买', 
        wait: async next => {
          await fetch('xxx') // 比如 请求接口
          next()
        }
      })
      dialogX.alert({message: '购买成功'})
    }
    

    Links

    demo 地址

    官网以及文档地址

    Github

    演示

    8.gif 8.gif 8.gif 8.gif 5738345-0b61e6d1d6a27605.gif

    第 1 条附言  ·  2019-11-19 13:50:44 +08:00
    我没说清楚 这个组件本身就是 then catch 这么使用的

    wait 参数只是一个用来增强的参数

    wait 的场景是 用户点击确认后还需进行的一些异步操作 比如请求接口之类的

    一般来说点击确认后弹窗会关闭 然后调用接口 这个时候需要弹出 loading 状态来阻止用户操作

    添加了 wait 参数后,用户点击确认后 弹窗不会关闭,但是状态转为 loading (会有一些样式的更改 并且阻止用户操作)

    等待 wait 函数中的请求执行完毕执行 next 弹窗才会关闭 其实就是省去了调用 loading 的一步
    第 2 条附言  ·  2019-11-19 17:57:58 +08:00
    感谢 @mcfog @zhw2590582 提的建议 这个仓库还有很大改进空间 😂
    19 条回复    2019-11-19 18:39:31 +08:00
    mcfog
        1
    mcfog  
       2019-11-19 12:33:06 +08:00 via Android   ❤️ 1
    总体还行,挑些毛病的话:

    已经 promise 和 async await 都上了还用 wait 这样的回调参数来做“后续干啥”,甚至这个回调参数里还有个 next callback 看着难受

    活动页弹个窗这种小事还带上 vue 难受
    yamedie
        2
    yamedie  
       2019-11-19 12:40:28 +08:00
    写法上, 感觉没有 vantUI 的$dialog.confirm().then().catch(), 链式调用来的优雅
    zhw2590582
        3
    zhw2590582  
       2019-11-19 12:46:06 +08:00   ❤️ 1
    next 可以省掉
    a62527776a
        4
    a62527776a  
    OP
       2019-11-19 13:24:06 +08:00
    @mcfog
    @zhw2590582 wait 回调参数的应用场景是这样的,
    用户点击确认后发送请求至接口 这段时间内弹窗不关闭 不允许用户做操作
    就是图 2 和图 4 的场景
    调用了 next 之后才会关闭弹窗
    如果没有这种场景就不需要 wait 参数来回调 就是正常的 Promise 函数
    a62527776a
        5
    a62527776a  
    OP
       2019-11-19 13:29:48 +08:00
    看来是我写的太令人容易误解了
    a62527776a
        6
    a62527776a  
    OP
       2019-11-19 13:33:19 +08:00
    @yamedie wait 只是一个增强的功能 正常就是 then catch 这么用的 /(ㄒoㄒ)/~~
    mcfog
        7
    mcfog  
       2019-11-19 14:07:03 +08:00 via Android   ❤️ 1
    @a62527776a next 仍然多余

    提供这样一个不上不下的功能没啥意思,不如给用户完全控制框里的渲染和逻辑的方式
    随便说几个场景吧:
    a)取消也要异步 block 住
    b)block 过程中用户希望在按钮上显示菊花 /其他文字
    c)block 过程中用户希望改变框内主体的展示,变灰加字进度条都有可能需要
    d)失败场景可能的需求有:框仍然消失 /框消失并通知外部改变状态 /框保留按钮变回可点 /框保留按钮状态改变 /弹第二个 alert 框告知用户失败并组合上述任意交互等等
    不管你的默认行为怎么写,总会有其他需求,诱惑你再加更多 option 和 callback
    问题的根源可能在于你没想清楚自己的组件的边界在哪里。我能猜到加这个 wait 的机制能满足你多数的需求,提高你的效率,但放到开源组件里,这个选项满足别人一半的需求,逼迫别人要么魔改 hack 要么不用,就是“不好用”的组件了
    wunonglin
        8
    wunonglin  
       2019-11-19 14:13:03 +08:00
    a62527776a
        9
    a62527776a  
    OP
       2019-11-19 15:45:05 +08:00
    @mcfog 这个功能我在 iOS 上经常有遇到过 我不大觉得这是个多余的功能

    你说的场景我觉得很有参考意义 比如:失败后框保留按钮变回可点 这个是我在 wait 函数中没有考虑到的 我觉得我会考虑加上这个功能

    我开发这个仓库的定位更多是实现面向 C 端用户的交互反馈 我想着能 cover 掉 ios 上弹窗的各种情况就可以了 应该不大适合需要定制化弹窗的面向企业的场景
    zhw2590582
        10
    zhw2590582  
       2019-11-19 17:29:42 +08:00   ❤️ 1
    哈哈,好吧,可能是我没理解你的用意吧,都已经用了 async await 了,假如异步操作 fetch 需要一秒时间,无论有没有 next,wait 都是经过一秒后执行完。
    a62527776a
        11
    a62527776a  
    OP
       2019-11-19 17:32:46 +08:00
    @zhw2590582 但是不调用 next 的话 程序就不知道是否结束了 next 就是用来结束程序的 loading 状态的
    zhw2590582
        12
    zhw2590582  
       2019-11-19 17:37:59 +08:00   ❤️ 1
    可以啊,这样不就好了

    async function wait() {
    await fetch("xxx");
    }

    (async () => {
    console.log("开始 loading");
    await wait();
    console.log("结束 loading");
    })();
    a62527776a
        13
    a62527776a  
    OP
       2019-11-19 17:39:09 +08:00
    @zhw2590582 我看看我 await 掉可不可以
    zhw2590582
        14
    zhw2590582  
       2019-11-19 17:39:38 +08:00   ❤️ 1
    应该返回一个 promise 才对

    async function wait() {
    return await fetch("xxx");
    }
    a62527776a
        15
    a62527776a  
    OP
       2019-11-19 17:52:12 +08:00
    @zhw2590582 😂运用不够灵活啊 谢谢你帮我优化代码
    a62527776a
        16
    a62527776a  
    OP
       2019-11-19 17:52:56 +08:00
    @zhw2590582 我看这样可以 我这就把代码修改掉
    liuxingbaoyu
        17
    liuxingbaoyu  
       2019-11-19 18:09:07 +08:00
    前几天还想找个类似的呢,强烈支持!
    a62527776a
        18
    a62527776a  
    OP
       2019-11-19 18:15:56 +08:00
    @wunonglin 你的意思是把 wait 作为链式调用吗?
    ChefIsAwesome
        19
    ChefIsAwesome  
       2019-11-19 18:39:31 +08:00
    因为对话框就是个 view,跟一个页面没啥区别。页面千变万化,从来没人说他可以写一个 page 组件就满足所有需求。所以对话框也一样,没有万能的。
    对话框最基本的功能是打开和关闭:
    应该有 onOpen,afterOpenAnimationEnd,onClose,afterCloseAnimationEnd 这样的事件。
    打开时,对话框的 zIndex 应该是可控的,如果支持打开多个对话框,最新的那个对话框应该层级最高。
    在背景上滚鼠标之类的操作,应该不会让页面滚动。点击背景是否应该关闭对话框,应该是个 property。
    按下 ESC 应该能关闭对话框。如果支持同时打开多个对话框,按下 ESC 应该只关闭最近打开的那个对话框。
    应该有个 property 强制对话框开启,按 ESC 之类的都不起作用。

    对话框里做异步操作,怎么禁用按钮,怎么显示 loading,跟对话框组件应该是没什么关系的。
    业务型的对话框应该是在普通对话框外面套一层,而不是给普通对话框加参数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5388 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 08:51 · PVG 16:51 · LAX 01:51 · JFK 04:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.