vlambda博客
学习文章列表

从单例模式看Vue单例组件

从单例模式看Vue单例组件

此篇文章是对从文档开始,重学Vue(上)的知识补充

什么是单例模式

单例模式可以说是众多设计模式的基石,今天我们不聊别的就说说单例模式

保证一个类仅有一个实例,并且提供一个访问它的全局访问点

之所以叫单例模式就是因为他保证了不管你调用我几次,老子就输出一次实例的特点,我们用ES6语法举个简单的例子

  • 非单例模式实现的类

    class Per {
      constructor(name) {
        this.name = name;
      }
      static sayName(name) {
        return new Per(name);
      }
    }
    var a = Per.sayName("码不停息");
    var b = Per.sayName("码不停息2");
    console.log(a); // Per {name: "码不停息"}
    console.log(b); // Per {name: "码不停息2"}
    console.log(a === b); // false
  • 单例模式实现的类

    class Per {
      constructor(name) {
        this.name = name;
      }
      static sayName(name) {
        if (!this.instance) {
          this.instance = new Per(name);
        }
        return this.instance;
      }
    }
    var a = Per.sayName("码不停息");
    var b = Per.sayName("码不停息2");
    console.log(a); // Per {name: "码不停息"}
    console.log(b); // Per {name: "码不停息"}
    console.log(a === b); // true

    可以看出,在非单例模式下我们调用几次sayName就会new几次Per并且每次new出来的结果不相同;在单例模式下不管你调用sayName几次,都会返回第一次的结果

单例模式的实际用途

  • 需要对页面资源进行统一调度。最典型的就是弹窗,单个弹窗当然没问题,但如果用户还没看清第一个弹窗的时候,第二个弹窗又来了,两个弹窗不管是覆盖还是叠加,体验都是极为糟糕的,这种时候就应该将所有弹窗放到一个单例下进行管理。
  • 需要复用对象以节约资源。比如使用 webSocket  与后台通信的时候。 webSocket虽然使用方便,但是多个 webSocket 连接会占用大量的服务端资源,因此,一个页面内绝对不能初始化多个接口相同的 webSocket。最好的实现是:同一个浏览器内不管有多少页面,都共享同一个连接,不过,维持连接的页面关闭的时候,其他页面需要及时发起新的连接来保持通信,这样的功能需要后端的支持才能达到。

手写 vue单例组件之全局提示框

  • 首先先做个提示框组件 toast.vue

    <template>
      <div class="app-toast info" v-if="isShow">
        {{ text }}
      </div>
    </template>
    <style scoped>
    .app-toast {
      position: fixed;
      left50%;
      top50%;
      background#ccc;
      padding10px;
      border-radius5px;
      transformtranslate(-50%, -50%);
      color#fff;
    }
    .info {
      background#00aaee;
    }
    </style>
  • toast.vue同级目录下新建index.js

    import vue from "vue";
    import toast from "./toast.vue";
    // 组件构造器,构造出一个 vue组件实例
    const ToastConstructor = vue.extend(toast);
    function showToast({ text, type, duration = 1000 }{
      this.toastDom = new ToastConstructor({
        eldocument.createElement("div"),
        data() {
          return {
            isShowtrue// 是否显示
            text: text, // 文本内容
          };
        }
      });
      // 添加节点
      document.body.appendChild(this.toastDom.$el);
      // 过渡时间
      setTimeout(() => {
        this.toastDom.isShow = false;
      }, duration);
    }
    // 全局注册
    function registryToast({
      vue.prototype.$toast = showToast;
    }
    export default registryToast;
  • main.js中去挂载

    import toastRegistry from "./components/Toast/index";
    Vue.use(toastRegistry);
  • 在项目文件使用

    this.$toast({
         text"我是消息"
    });

    这就是典型的单例组件

总结

我们基于vue实现了一个单例组件并封装成插件,而在做项目时,我们往往会使用各种大型的UI组件库,用别人给我们写好了轮子,虽然加快了项目进度,但也让容易我们忽略一些最本质的东西。

交个朋友吧

让代码永不停息


码不停息