单例模式在前端的应用

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
一般可以用一个变量去标记,是否已经为某个类创建过实例,如果是,则返回该实例,如果不是,则创建新的实例。
Vuex中的单例模式
其实不管是Vuex还是Redux,它们都采用了单例模式。两者都用一个全局的唯一Store来存储所有状态。

在Vue项目中,我们通过 Vue.use(Vuex) 来安装Vuex插件,该插件是一个对象形式,内部实现一个install方法。在安装插件时,会调用该方法,然后把store注入Vue实例中。
在install方法中采用单例模式,控制store全局唯一。
let Vue // 利用闭包保存变量不被销毁 ...export function install (_Vue) { // 判断传入的Vue实例对象是否已经被install过Vuex插件(是否有了唯一的state) if (Vue && _Vue === Vue) { if (process.env.NODE_ENV !== 'production') { console.error( '[vuex] already installed. Vue.use(Vuex) should be called only once.' ) } return } // 若没有,则为这个Vue实例对象install一个唯一的Vuex Vue = _Vue // 将Vuex的初始化逻辑写进Vue的钩子函数里 applyMixin(Vue) }

  • 通过闭包保存标志量,不被销毁
  • 判断vue实例是否已经注入过store,如果是直接返回
  • 若没有,则为这个实例对象创建一个唯一的Vuex,将Vuex的初始化逻辑写进Vue的钩子函数里。
思考:如果install函数中不采用单例模式会发生什么?
若不使用单例模式,并且多次调用 Vue.use(Vuex),那么会给Vue实例注入新的store,之前的数据都会清空。
单例模式的应用
实现一个Storage 描述:实现Storage,使得该对象为单例,基于 localStorage 进行封装。实现方法 setItem(key,value) 和 getItem(key)。
方法一:静态方法版
// 静态方法版 class Storage { static getInstance() { // 判断是否已经有实例 if (!Storage.instance) { // 没有则创建 Storage.instance = new Storage(); } // 有则返回 return Storage.instance; }getItem(key) { return localStorage.getItem(key); }setItem(key, value) { return localStorage.setItem(key, value); } }const storage1 = Storage.getInstance(); const storage2 = Storage.getInstance(); storage1.setItem('name', 'pengpeng'); storage2.setItem('name', 'linlin'); console.log(storage1.getItem('name')); // linlin console.log(storage1 === storage2); // true

【单例模式在前端的应用】方法二:闭包版
// 闭包版 // 1、基础的StorageBase类,把getItem和setItem方法放在它的原型链上 function StorageBase() { }; StorageBase.prototype.getItem = function (key) { return localStorage.getItem(key); }; StorageBase.prototype.setItem = function (key, value) { return localStorage.setItem(key, value); }// 2、创建构造函数,利用闭包以及立即执行函数 const Storage = (function () { let instanse = null; return function () { if (!instanse) { instanse = new StorageBase(); } return instanse; } })(); const storage3 = new Storage(); const storage4 = new Storage(); storage3.setItem('age', 18); storage4.setItem('age', 22); console.log(storage3.getItem('age')); // 22 console.log(storage3 === storage4); // true

实现一个全局的模态框
单例模式弹框 - 锐客网#modal { height: 200px; width: 200px; line-height: 200px; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); border: 1px solid black; text-align: center; }

    推荐阅读