从JavaScript单例模式到Vuex中store

时间:2024-10-07 12:09:57

导言:如果你像我一样也是JavaScript的初学者并且希望更深一步理解Vue框架背后的设计思想的话,那么这篇文章或许会适合你。

单例模式

单例模式的定义是:

保证一个类仅有一个实例,并提供一个访问他的全局方法。

什么是单例模式呢,简单来说就是一个类只能创建一个实例,即使你创建了很多的实例,但如果通过===比较的话,你会发现,这些实例全部都是相等的。

那这有什么用呢?比如我们拿微信举例子,通常情况下无论是手机端还是PC端,你都只能登陆一个微信账号。而且你也只能打开一个微信登录界面,没有办法打开多个。这就是单例模式的一个应用场景,当我们会做一些限制操作的时候,会考虑使用单例模式。


JavaScript实现单例模式

在JavaScript中一个非常有用的单例模式实现方式称为惰性单例。我们希望单例模式是按需加载的,也就是需要单例模式的时候才生成单例模式对象,不需要的时候就不生成单例模式对象。代码实现如下:

class SingleObject {
  login() {
      console.log('login...')
  }
}

// 定义一个静态方法
SingleObject.getInstance = (function () {
  let instance
  return function () {
      if (!instance) {
          instance = new SingleObject();
      }
      return instance
  }
})()

// 测试:注意这里只能用静态函数getInstance, 不能new SingleObject() 
let obj1 = SingleObject.getInstance()
obj1.login()  // login...
let obj2 = SingleObject.getInstance()
obj2.login()  // login...
console.log(obj1 === obj2)  // true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
'
运行

当我们以后调用的时候就会创建对应的单例模式对象。

我们根据单例模式这种设计思想,就可以实现微信登录只能同一时间保持打开一个登录页的功能。

const createLoginLayer = (function () {
  let div
  return function() {
    if (!div) {
      div = document.createElement('div')
      div.innerHTML = '我是微信登录页面'
      div.style.display = 'none'
      document.body.appendChild(div)
    }
    return div
  }
})()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
'
运行

但我们上面的代码有一点小小的瑕疵。比如你有一个微信登录页功能想要使用单例模式,后面又来了一个登录后退出功能也想用单例模式,难道我们要把这样的代码结构再复制一遍吗?可能此时你会想,要是我们能把这内在的逻辑结构抽象成一个统一的组件,然后使用单例模式的时候调用这个组件就好了。下面我们来试试看:

const getSingle = function(fn) {
  let result
  return function() {
    return result || (result = fn.apply(this, arguments))
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
'
运行

我们创建一个getSingle函数,它的参数是一个函数,可以用来传入我们想要实现单例模式的功能函数。因为返回的是一个函数,里面有result参数,所以变量result不会因子调用getSingle结束之后被销毁。类似于之前单例模式的div判别功能。

下面我们用定义的新方法实现微信登录页面的单例模式。

const createLoginLayer = function() {
  const div = document.createElement('div')
  div.innerHTML = '我是微信登录页面'
  div.style.display = 'none'
  document.body.appendChild(div)
  return div
}

const createSingleLoginLayer = getSingle(createLoginLayer)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Vuex中store

我们知道Vuex是用来做状态存储或者是数据存储的。我们想要不同页面访问获得的这个store值是完全一样的,这样才可以实现不同页面数据保持同步。所以store是通过单例模式实现的。


参考资料

[1] 《JavaScript设计模式与开发实践》