前言

目录整理:
设计模式在vue中的应用(一)
设计模式在vue中的应用(二)
设计模式在vue中的应用(三)
设计模式在vue中的应用(四)
设计模式在vue中的应用(五)
设计模式在vue中的应用(六)

为什么要写这些文章呢。正如设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结(来自百度百科)一样,也是想通过分享一些工作中的积累与大家探讨设计模式的魅力所在。
在这个系列文章中为了辅助说明引入的应用场景都是工作中真实的应用场景,当然无法覆盖全面,但以此类推也覆盖到了常见的业务场景



这一篇要讲的可能和之前有点区别,前面几篇要达到我们的目的不得不造出很多对象(组件),而本文的主角是让我们减少对象——享元模式。
定义(来自网络):

享元模式使用共享技术实现相同或者相似对象的重用。也就是说实现相同或者相似对象的代码共享。

使用场景(来自百度百科):

如果一个应用程序使用了大量的对象,而这些对象造成了很大的存储开销的时候就可以考虑是否可以使用享元模式。

一、需求

截图来自iView官方文档(Message组件)

Message组件相信大家不会陌生,不知道大家有没有亲自实现过

二、需求分析

Message组件有以下几个特点:

  • 交互方式一样
  • 有三种类型:successwarningerror,对应三种不用的页面效果:提示icon、背景样式、字体样式
  • 接收一段提示文字

可以知道:

交互方式——弹出、隐藏,由共享对象所拥有

提示icon、背景样式、字体样式提供接口可配置

使用api统一

三、设计实现

常规使用方式this.$Message.success()this.$Message.warning()this.$Message.error()所以我们需要以vue插件的形式扩展vue的prototype

//Message.js 伪代码
export default {install (Vue) {// 扩展Vue的`prototype`Vue.prototype.$Message = {success (text) {// 通常我们可能如下操作,每次new一个新的组件对象const Dialog = new Vue({...})document.body.appendChild(Dialog.$el)},warning (text) {// 同上,new一个新的组件对象const Dialog = new Vue({...})document.body.appendChild(Dialog.$el)},error (text) {// 同上,new一个新的组件对象const Dialog = new Vue({...})document.body.appendChild(Dialog.$el)}}}
}
复制代码

如上例子所示每次使用Message组件都需new一个Dialog出来,下面我们使用享元模式的思想达到减少组件对象的目的

//Message.js 伪代码
export default {install (Vue) {// 在使用插件Vue.use(Message)时实例化一个Dialog组件对象const Dialog = new Vue({data () {return {icon: '',fontStyle: '',backgroundStyle: '',text: ''}}...})// 扩展Vue的`prototype`Vue.prototype.$Message = {success (text) {// 改变Dialog的data.xx的值触发Dialog的更新Dialog.icon = successIconDialog.fontStyle = successFontStyleDialog.backgroundStyle = successBackgroundStyleDialog.text = text// 获取Dialog的最新DOM添加到body标签中document.body.appendChild(Dialog.$el)},warning (text) {// 同上...document.body.appendChild(Dialog.$el)},error (text) {// 同上...document.body.appendChild(Dialog.$el)}}}
}
复制代码

四、结果

都说做事是结果导向的,现在看看我们的设计得到了什么结果

Dialog只会在项目初始化时被new一次,每次使用Message组件通过改变Dialog的状态获取组件DOM,其实很容易知道new一个组件的成本要比一个组件的更新成本高很多

与常规的实现方案相比缺点是就算没使用也会执行new Dialog()并占用内存

五、附完整实现(示例)

如有bug还请见谅随手写的

import './index.scss'let zIndex = 2001;export default {install (Vue) {const Dialog = new Vue({data () {return {text: '这是一个提示',icon: 'icon-waiting',iconColor: '#308AFE',background: '#ddd'}},render (h) {zIndex++const selfStyle = {background: this.background,zIndex}return h('div',{class: 'm-message',style: selfStyle},[h('i', {style: {marginRight: '8px', color: this.iconColor},class: `iconfont ${this.icon}`}),this.text])}}).$mount()function appendDialog(message, icon, iconColor, bgColor, time = 3) {Dialog.text = messageDialog.icon = iconDialog.iconColor = iconColorDialog.background = bgColorlet timer = ''let element = document.createElement('div')Dialog.$nextTick(() => {element = Dialog.$el.cloneNode(true)document.body.appendChild(element)})if(time > 0) {timer = setTimeout(() => {element.classList.add('outer')setTimeout(() => {document.body.removeChild(element)}, 500);clearTimeout(timer)}, time * 1000);}}Vue.prototype.$message = {tips (message, time) {appendDialog(message, 'icon-waiting', '#308AFE', '#ADD8F7', time)},warning(message, time) {appendDialog(message, 'icon-warn', '#FFAF0D', '#FCCCA7', time)},success(message, time) {appendDialog(message, 'icon-success', '#36B37E', '#A7E1C4', time)},error(message, time) {appendDialog(message, 'icon-error', '#E95B5B', '#FFF4F4', time)},destory() {document.querySelectorAll('.m-message').forEach(ele => ele.remove())}}}
}
复制代码

六、总结

回想一下在讲解讲享元模式时大多会例举的一个场景

有男女衣服各50套,现在要给这些衣服拍照怎么办呢?土豪做法:new 100个模特对象一人穿一套慢慢拍,有钱任性(内存占有率高)
理性做法:new 一个男模特和一个女模特拍完一套换一套接着拍(暴露一个换衣服的接口),也没差,主要是省钱(对象从100个减少为2个)
复制代码

熟悉设计模式同学的可能觉得这个场景不太好,我认同你的观点,不过用来学习享元模式个人觉得还能接受。
Message组件的具体实现方案不拒绝也不推荐本文的方式(哈哈哈~)

更新:发现elemnet-ui的MessageBox组件就是类似的思路传送门


本文实现同样适用于react,为什么文章以vue做题?vue的template让我们在理解一些概念的时候可能会有点不适应,而react的jsx可以看做就是在写JavaScript对各种概念实现更灵活
友情提示:设计模式在vue中的应用应该会写一个系列,喜欢的同学记得关注下

设计模式在vue中的应用(五)相关推荐

  1. Vue中Vuex的五个属性和基本用法

    一.Vuex的五个核心概念:state.getters.mutations.actions.modules 1.state: vuex的基本数据,用来存储变量: 2.getters: 从基本数据(st ...

  2. 系列九、vue中css样式字体设置为华文行楷

    一.下载华文行楷字体 # 下载地址 https://file.diyiziti.com/front/download/common/download?id=91# 百度网盘分享地址 链接:https: ...

  3. uml和模式应用 pdf_总结分享:PHP中常见的五种设计模式

    设计模式不仅代表着更快开发健壮软件的有用方法,而且还提供了以友好的术语封装大型理念的方法.例如,您可以说您正在编写一个提供松散耦合的消息传递系统,也可以说你正在编写名称为 观察者 的模式. 用较小的示 ...

  4. python和php互动_PHP中常见的五种设计模式

    您可能感兴趣的文章: 设计模式只是为 Java架构师准备的 - 至少您可能一直这样认为.实际上,设计模式对于每个人都非常有用.如果这些工具不是 "架构太空人" 的专利,那么它们又是 ...

  5. PHP中常见的五种设计模式

    设计模式只是为 Java架构师准备的 - 至少您可能一直这样认为.实际上,设计模式对于每个人都非常有用.如果这些工具不是 "架构太空人" 的专利,那么它们又是什么?为什么说它们在 ...

  6. 探讨Vue 数据监测原理-第五节-展开介绍 Vue中监测-【数组】数据的原理

    文章目录 探讨一下Vue 数据监测的原理 本次探讨共的第五个章节 第五节:展开介绍 Vue中监测-[数组]数据的原理 1. 案例 1.1. 页面案例 2. 数组形式|对象形式爱好的区别 2.1. 页面 ...

  7. JS【发布订阅设计模式】在vue中的实际运用

    什么是发布订阅模式? 订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象.这个主题对象在自身状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态. 比如addEv ...

  8. 五十九、Vue中的样式绑定

    @Author:Runsen @Date:2020/10/16 大四是一个焦虑的时期.烦恼有时候是具体问题带来的压力,有时候却是无端的.莫名其妙的,有时候还极易受到外界的影响,别人一句话就会激起内心难 ...

  9. 五-2、vue中引用文件路径问题

    vue路径分为: 绝对路径.相对路径.~+路径 及 别名+路径 绝对路径: (1)放在public文件夹下的内容,不会经过webpack打包处理,可以直接引用, 比如:aa.png直接放在public ...

最新文章

  1. IdentityServer4【Introduction】之支持的规范
  2. python如何使用字典_python字典怎么使用zip
  3. Android RaingBar评分条的使用
  4. SQL Server经典查询语句练习题及答案
  5. (35)Verilog HDL算术运算:取模、指数、对数
  6. 数据库工作笔记017---还记得Oracle悲观锁和乐观锁嘛?以及hibernate对乐观悲观锁的封装
  7. php环境搭建及入门
  8. Android 字母导航条实现
  9. angular表单验证
  10. TCP实现原理(拥塞控制)
  11. JAVA语法——选择排序
  12. ubuntu php加载不了gd,ubuntu 中php不支持gd库的freetype,导致页面验证码无法加载
  13. java9最新下载_java9下载_java9官方版下载 32位64位 最新版_天天下载手机版
  14. 微型四轴飞行器(1)
  15. 关于我的 “二进制部署 kubernetes 集群” 的体验
  16. 较全的正则字符、规则汇总
  17. Laravel 使用Dingo API
  18. Thread out-of-synch 错误
  19. EasyExcel 筛选导出
  20. maven完全离线开发【解决jar包自动从网络下载导致打包失败】

热门文章

  1. 在JavaScript中使用json.js:访问JSON编码的某个值
  2. LLBL Gen Pro 设计器使用指南
  3. java lr分析表建立程序_[源码和文档分享]基于Java实现的LR(1)分析法语法分析程序...
  4. 投稿Cover Letter如何写出彩
  5. fireworks CS5安装教程
  6. new ArrayList 报错
  7. 计算机视觉与深度学习 | 基于多源传感器数据融合的动态场景SLAM研究
  8. java 找不到方法,已经定义的方法找不到
  9. tgz文件linux打开,tgz文件扩展名,tgz文件怎么打开?
  10. 目标检测(R-CNN、Fast R-CNN、Fater R-CNN)