单例模式
保障一个类仅有一个实例,并提供一个拜访它的全局拜访点。
个别能够用一个变量去标记,是否曾经为某个类创立过实例,如果是,则返回该实例,如果不是,则创立新的实例。
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')); // linlinconsole.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')); // 22console.log(storage3 === storage4); // true
实现一个全局的模态框
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>单例模式弹框</title></head><style> #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; }</style><body> <button id='open'>关上弹框</button> <button id='close'>敞开弹框</button></body><script> // 外围逻辑,这里采纳了闭包思路来实现单例模式 const Modal = (function () { let modal = null return function () { if (!modal) { modal = document.createElement('div') modal.innerHTML = '我是一个全局惟一的Modal' modal.id = 'modal' modal.style.display = 'none' document.body.appendChild(modal) } return modal } })() // 点击关上按钮展现模态框 document.getElementById('open').addEventListener('click', function () { // 未点击则不创立modal实例,防止不必要的内存占用;此处不必 new Modal 的模式调用也能够,和 Storage 同理 const modal = new Modal() modal.style.display = 'block' }) // 点击敞开按钮暗藏模态框 document.getElementById('close').addEventListener('click', function () { const modal = new Modal() if (modal) { modal.style.display = 'none' } })</script></html>