前端开发设计模式 | 青训营笔记

56 阅读4分钟

这是我参与「第四届青训营」笔记创作活动的的第5天

浏览器中设计模式

传统设计模式:单例模式

  • 定义:全局唯一访问对象,如window对象。
  • 应用场景:实现缓存、全局状态管理等。
  • 比如以下请求缓存例子:cache作为全局对象,任何地方都可以使用保存响应结果;request为缓存方法。
  • 第一次调用时,cache中还未存储响应结果,需要先发送请求获取响应结果,因此等待的时间会较长;第二次由于保存了发送请求后得到的响应结果,故等待时间较短。
    const cache={}   
    export const request = async(url:string)=>{
        if(cache[url]) return cache[url]
        const response = await api(url)
        cache[url] = response
        return response
    }
    

发布订阅模式

  • 定义:在被订阅对象发生变化时通知订阅者。
  • 应用场景:邮件订阅、上线订阅等。通俗地讲,比如在Bilibili、Youtube中,你关注的博主发布了动态和视频,自己会接收到他们的发布通知。
  • 以下为用户上线订阅例子。Notify为消息通知函数。包含订阅和上线发布方法。
  • 默认构建用户是不在线的。关注用户时,会将用户信息与通知消息插入follower列表中;当用户上线时,会给自己的follower发送上线通知。
    type Notify = (user=User) =>void  //通知函数
    export class User {
        constructor(name){ ... } //包含follower列表
        subscribe(user = User,notify = Notify){
            User.folowers.push({user,notify})  //新增订阅者
        }
        online(){  ... //状态修改操作
            this.followers.forEach(({notify})=>{
                notify(this) //上线时通知follower
            })
        }
    }
    

JavaScript设计模式

原型模式

  • 定义:用已有对象创建新对象。
  • 例子:使用原型模式创建上线订阅中的用户。
  • JavaScript中Object提供有创建对象方法Object.create(),可以在源对象的基础上创建新的对象,新对象可以使用源对象提供的属性和方法。
    export const createUser = (name) =>{
        const user = Object.create(User)
        ... //属性赋值操作
        return user
    }
    
  • 目前很少使用该方法了。

代理模式

  • 定义:可自定义控制原型对象的访问方式,并允许在更新后做一些额外处理。
  • 应用场景:监控、代理工具、前端框架实现等。
  • 所谓代理,就是有一个替身代理对象去控制源对象的,避免对源对象直接操作。在替身代理对象中对请求进行处理后再转交给源对象。 proxy.png
  • 如下例子:使用代理模式实现用户在线状态订阅。
  • 在代理对象中,如要改变用户的上线状态时,会触发通知函数(通知followers用户上线了)。
    const proxyUser = new Proxy(user,{ //代理用户
        set(target,prop,value){  
            target[prop] = value
            if(prop === 'status'){
                notifyStatusHandler(target,value)   //当修改user中的状态时触发通知状态函数
            }
            return true
        }
    })
    
  • 一些其他代理模式案例:
    • 图片预加载:当上传的图片过大时,可以用一张本地的图片先进行占位,等图片异步加载完成后再进行替换。
    • 缓存代理:存储先前发送的请求结果,在下次请求时如果传入的参数一致,则返回先前的存储结果。

其他JS代理案例资料参考

迭代器模式

  • 定义:在不暴露数据类型的情况下访问集合中的数据。
  • 应用场景:数据结构中多种数据类型:列表、树等,可以提供通用操作接口。
  • 比如用for...of迭代组件。

前端框架设计模式

代理模式

  • 对DOM操作代理,比如前端框架中常用的MVVM模型。
  • 拿Vue作为例子,Vue实例即数据代理。M(数据模型)-V(视图模型)-VM(Vue实例)模型中,通过VM对象代理data对象中属性,可以更方便操纵data中的数据。
  • Vue实例数据代理原理:通过Object.defineProperty()把数据模型对象中所有属性都加到VM上,每个被VM代理的属性都有get()set()方法去获取、改变属性值。

组合模式

  • 定义:多个对象组合使用,也可以单个对象独立使用。
  • 应用场景:DOM、前端组件、文件目录、部门等。