前端设计模式

前言

该篇文章主要介绍一些在前端中的设计模式及其应用,如单例模式、发布订阅模式、原型模式、代理模式等。

1. 概述

什么是设计模式

设计模式是软件设计中常见问题的解决模型:

  • 是历史经验的总结
  • 与特定语言无关,是实现某种需求的方法

设计模式趋势

前端设计模式

设计模式分类

有23种设计模式分为:

  • 创建型 – 如何创建一个对象
  • 结构型 – 如何灵活的将对象组装成较大的结构
  • 行为型 – 负责对象间的高效通信和职责划分

2. 浏览器API中的设计模式

2.1 单例模式

「定义」

  • 全局唯一访问对象,在任何地方访问都会返回唯一对象,在任何地方修改都会修改该唯一对象

「应用场景」

  • web应用中的全局缓存
  • 如react、Vue中的状态管理

「举例」

  1. 浏览器中的window对象前端设计模式

  2. 用单例模式实现请求缓存:用类实现

//用单例模式实现请求缓存
import {api} from '../utils/index'

export class Request{
   static instance: Request;

   private cache: Record<string,string>;

   constructor(){
       this.cache = {};
  }

   static getInstance(){
       if(this.instance){
           return this.instance;
      }
       this.instance = new Request();
       return this.instance;
  }

   public async request(url:string){
       if(this.cache[url]){
           return this.cache[url];
      }
       const response = await api(url);
       this.cache[url] = response;
       return response;
  }
}

Request类的instance属性存储全局唯一的Request 对象,cache 存储全局缓存。

Request类通过getInstance静态方法来获取全局唯一的 Request对象,通过request 公共方法来对请求进行包装,当这个url已经请求过就取cache中对应url的缓存数据。

测试:前端设计模式

  1. 用单例模式实现请求缓存:用方法实现
//用单例模式实现请求缓存
import {api} from '../utils/index'

const cache: Record<string,string> = {}; // 全局唯一缓存对象

export const request = async (url:string) =>{
  if(cache[url]){
   return cache[url];
  }
  const response = await api(url);
  cache[url] = response;
  return response;
}

测试:前端设计模式

2.2 发布订阅模式(观察模式)

「定义」

  • 一种订阅机制,可在被订阅对象发生变化时通知订阅者

「应用场景」

  • 从系统架构之间的解耦(消息队列,Redis缓存),到业务中一些实现模式,像邮件订阅,上线订阅等,应用广泛。
  • 如vue中组件之间通信方式

「举例」

  1. 浏览器中的事件绑定
    • 我们给按钮button绑定一个事件click,点击按钮后就触发函数doSomthing...
    • 订阅对象就是按钮button,使订阅对象发生 变化的契机就是点击按钮,订阅者就是绑定的函数doSomting..,点击按钮后订阅者就做一些事情。
前端设计模式
  1. 用发布订阅模式实现用户上线订阅

前端设计模式第一行的 Notify 是用来定义一个函数类型。

User类:

  • name属性定义创建对象时,对象的名称。

  • status属性用于表示该用户是否上线:offline下线,online上线

  • followers:用于存储订阅该对象的数组,数组中存储订阅该对象的对象以及传入的函数。

构造函数用于完成对象的初始化。

  • subscribe函数用于完成订阅对象这个行为,user参数传入要订阅的对象,notify传入函数,然后放入被订阅者的followers数组中。

  • online函数用来执行对象上线的动作,并通知订阅者,执行订阅的函数。

测试:

创建三个对象user1 user2 user3user1 user2 去订阅user3,传入执行函数。user3上线就执行订阅者user1 user2的传入的函数。前端设计模式

3. JavaScript中的设计模式

3.1 原型模式

「定义」

  • 复制已有对象来创建新的对象

「应用场景」

「举例」

用原型模式创建上线订阅中的用户前端设计模式我们通过对象字面量来存储User对象的相关属性和方法。通过createUser方法来创建User对象,通过该方法中的Object,create,会基于已有对象来返回一个新的对象

测试前端设计模式

3.2 代理模式

「定义」

  • 可自定义控制对原对象的访问方式,并且允许在更新前后做一些额外处理

「应用场景」

  • 监控,代理工具,前端框架实现(vue中的数据劫持,)等等。

「举例」

使用代理模式实现用户状态订阅:

  • 我们上边的例子中online函数做了两件事情,一是用户上线,二是通知订阅者。

  • 我们在实际开发中应尽量满足一个函数只做一件事,那么我们可以通过代理模式来实现通知订阅者,而online函数只进行对象上线操作,如下图。前端设计模式

实现真正的通知订阅者行为:

  • 通过createProxyUser来创建User的代理对象,通过创建Proxy,传入被代理对象user,以及传入需要进行的操作,有两个函数getsetget用于获取user对象时进行一些操作,set用户设置user对象时进行一些操作,这里我们只需要set

  • set函数参数target指代被代理对象userprop指定被代理对象的属性,value表示设置的值。

  • 这个set函数做的事情是,当对被代理对象中的属性赋值时,先进行赋值操作(this.status = "online"),再判断该prop属性是不是status,如果是就执行notifyStatusHandlers函数;该函数会判断传入值value是不是online,如果是就通知订阅者该用户已上线。前端设计模式

3.3 迭代器模式

「定义」

  • 在不暴露数据类型的情况下访问集合中的数据

「应用场景」

  • 数据结构中有多种数据类型,列表、数等,提供通用操作接口。

「举例」

  1. JavaScript中的for of前端设计模式

  2. for of迭代所有组件

创建一个MyDomElement类,tag属性表示组件名称,children表示承载该组件的所有子组件数组,addChildren用来添加子组件。前端设计模式

通过Symbol.iterator方法将对象变成可迭代对象;这个方法返回一个对象,对象中有一个函数next ,会遍历出所有的子组件,进行返回;返回值是一个对象,有两个参数:vaule表示返回的值,done表示是否迭代完成。前端设计模式

测试前端设计模式

4. 前端框架中的设计模式

主要介绍代理模式和组合模式

4.1 代理模式

「举例」

Vue 组件实现计数器

前端设计模式

前端设计模式这是实现的代码,通过点击按钮,使count+1,但是为什么页面会自动更新,不应该进行DOM操作吗,这就是我们要讲的前端框架中对DOM操作的代理。

前端设计模式

先看有框架前后的视图更新我们是怎么做的:

  • 前:当我们更新DOM属性count时,我们通过innerText来更新视图中的count值。

  • 后:当我们更新DOM属性count时,先有框架对虚拟DOM更新,然后通过Diff算法比对何处变化,由框架来完成视图的更新,我们只需要更新数据,就会自动更新视图。

DOM更新前后的钩子:当我们点击按钮count值+1时,就会输出更新前后的值前端设计模式前端设计模式

4.2. 组合模式

「定义」

  • 可多个对象组合使用,也可单个对象独立使用

「应用场景」

  • DOM结构,前端组件(多个组件组成一个页面),文件目录,部门

「举例」

React的组件结构:

调用setCount时,设计一个队列对count进行主动更新,也是对DOM做代理,但不是JavaScript中的Proxy前端设计模式

Count组件可以作为一个独立的组件进行渲染,也可以作为一个组件的一部分。前端设计模式

5. 总结

  • 总结出抽象的模式相对比较简单,但是想要将抽象的模式套用到场景中非常困难。
  • 现代编程语言的多编程范式带来的更多可能性,响应式编程,函数式编程。
  • 可以通过优秀的开源项目学习设计模式并不断实践。

原文始发于微信公众号(yanghi):前端设计模式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/226874.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!