掌握前端开发中的单例模式——模态窗口实战

312 阅读6分钟

阅读时间约 8 分钟。


大家好!在《闭包私有化变量:实现安全高效的单例模式》和《前端登录态管理神器:单例模式的实践与应用》中我们介绍了两种单例模式的应用示例,现在继续我们的单例模式探讨之旅。

今天我们来聊聊如何在前端开发中优化模态窗口的应用。

依照惯例,我们先看效果图:

单例模式实现的模态窗口

文末提供源码仓库

1. 模态窗口:大家的老朋友

模态窗口,或者说弹窗,是大家非常熟悉的前端 UI 组件。它可以用来展示警告、通知或者和用户互动的表单等内容。弹出模态窗口时,页面其他内容会被遮挡,用户需要先处理弹窗才能继续操作。

2. 单例模式:模态窗口的好帮手

在开发中,我们可能需要创建很多模态窗口。但同时显示多个弹窗会让界面变得混乱,影响用户体验。单例模式就派上用场了,确保同一时间只有一个模态窗口实例存在,从而提升性能和用户体验。

3. 实践:单例模式的模态窗口

下面是一个简单的使用单例模式的模态窗口实现:

class Modal {
  private static instance: Modal;

  private constructor() {}

  static getInstance(): Modal {
    if (!Modal.instance) {
      Modal.instance = new Modal();
    }
    return Modal.instance;
  }

  public open(content: string): void {
    // 创建模态窗口的DOM结构,并将内容添加到模态窗口中
    // 显示模态窗口
  }

  public close(): void {
    // 关闭模态窗口,并销毁模态窗口的DOM结构
  }
}

const modal = Modal.getInstance();
modal.open("这是一个模态窗口");

这段代码向我们展示了如何使用单例模式来创建模态窗口。

首先,我们创建了一个名为 Modal 的类。这个类有一个静态属性 instance,用来保存这个类的唯一实例。注意这里我们将构造函数设置为私有,这样就避免了在类外部使用 new 关键字创建新的 Modal 实例,保证了单例模式的正确实现。

接下来,我们定义了一个静态方法 getInstance(),它的作用是获取 Modal 类的唯一实例。在这个方法中,我们检查 instance 是否已经存在,如果不存在,我们就创建一个新的 Modal 实例并将其赋值给 instance。然后返回 instance。这样,每次调用 getInstance() 时,我们都会得到相同的 Modal 实例。

此外,我们在 Modal 类中定义了两个公共方法:opencloseopen 方法接收一个字符串参数 content,表示模态窗口的内容。在这两个方法中,我们需要根据实际需求添加逻辑来创建和销毁模态窗口的 DOM 结构。这部分逻辑在这段代码中还没有实现,你可以自己尝试补充哦!

最后,我们通过调用 Modal.getInstance() 获得 Modal 类的唯一实例,然后使用这个实例调用 open 方法来打开模态窗口。这样一来,我们就实现了一个简单、易用的模态窗口,同时保证了模态窗口实例的唯一性,提高了应用的性能和用户体验。

4. 好处与局限

单例模式的模态窗口有以下优势:

  1. 同时只有一个模态窗口实例,避免资源浪费;
  2. 避免多个模态窗口同时显示,提高用户体验;
  3. 提高代码的可维护性和可读性。

但它也有一些局限性:

  1. 无法同时处理多个模态窗口需求;
  2. 单例模式可能导致全局变量污染,需谨慎使用。

5. 改进与扩展

针对局限性,我们可以根据实际需求改进和扩展。例如:

  1. 队列化模态窗口:顺序存储多个模态窗口,一个关闭后再显示下一个。这样既避免同时显示多个模态窗口,又满足处理多个模态窗口的需求。

    class Modal {
      private static instance: Modal;
      private queue: string[];
    
      private constructor() {
        this.queue = [];
      }
    
      public static getInstance(): Modal {
        if (!Modal.instance) {
          Modal.instance = new Modal();
        }
        return Modal.instance;
      }
    
      public open(content: string): void {
        this.queue.push(content);
        if (this.queue.length === 1) {
          this.show();
        }
      }
    
      public close(): void {
        this.queue.shift();
        if (this.queue.length > 0) {
          this.show();
        } else {
          // 销毁模态窗口的DOM结构
        }
      }
    
      private show(): void {
        // 创建模态窗口的DOM结构,并将队列中的第一个内容添加到模态窗口中
        // 显示模态窗口
      }
    }
    
    const modal: Modal = Modal.getInstance();
    modal.open("这是一个模态窗口");
    modal.open("这是另一个模态窗口");
    

    在这个版本的 Modal 类中,我们看到一些新的变化。首先,我们为这个类添加了一个新的私有属性 queue,它是一个字符串数组,用于存储要显示的模态窗口内容。构造函数中,我们将其初始化为空数组。

    getInstance() 方法和之前的实现相同,用于获取 Modal 类的唯一实例。然后,我们有两个公共方法:openclose 和一个新的私有方法 show

    open 方法现在将接收到的内容添加到 queue 中。然后,如果 queue 的长度为 1,即当前只有一个模态窗口需要显示,我们调用 show 方法。这个改动使得我们可以将多个模态窗口的内容加入队列,并逐个显示。

    close 方法中,我们从 queue 中移除第一个元素。如果 queue 非空,我们继续调用 show 方法来显示下一个模态窗口。否则,销毁模态窗口的 DOM 结构。

    show 方法是一个私有方法,用于创建模态窗口的 DOM 结构,并将队列中的第一个内容添加到模态窗口中。然后显示模态窗口。这个方法在 openclose 方法中被调用,用于处理模态窗口的显示逻辑。

    最后,我们通过调用 Modal.getInstance() 获得 Modal 类的唯一实例,然后使用这个实例调用 open 方法来打开模态窗口。在这个例子中,我们连续调用了两次 open 方法,将两个模态窗口的内容加入到队列中。当我们调用 close 方法时,会依次显示队列中的模态窗口。

  2. 使用命名空间或模块化技术,将单例模式与其他模式结合使用,减少全局变量污染。例如,在将来讨论工厂模式时,我们可以尝试这样的实现。

6. 总结

通过这篇文章,我们学会了如何在模态窗口中应用单例模式,以及如何优化和扩展它。使用单例模式可以确保模态窗口的唯一性,提高前端应用的性能和用户体验。同时,我们也要关注单例模式的局限性,并根据实际需求进行相应的改进。希望这篇文章能帮助你在前端开发中更好地运用单例模式,提升代码质量。

如果你觉得这篇文章对你有帮助,别忘了点赞、分享给更多的朋友,也可以关注我们的微信公众号「码上花甲」,获取更多前端开发干货和资源。

感谢阅读,我们下期再见!


源码在 Github 仓库,戳这里 👈