day23 设计模式

回顾

ajax

ajax是一个异步的请求工具,主要提供对应的客户端和服务端之间的数据交互。它可以完成对应的局部刷新(同步加载页面整体会刷新,异步加载对应的页面不会进行刷新)核心对象
XMLHttpRequest)。

ajax的流程

  • 创建xhr对象
  • 打开连接
  • 设置对应请求头
  • 发送请求
  • 监听事件接收数据(onreadystateChange)

get请求

get请求数据携带在对应的url中

post请求

post需要设置对应的请求头

xhr.setRequestHeader('Content-type','x-www-form-urlencoded')

post请求携带在请求体中

xhr.send(body)

JSONP

解决对应的跨域方案(主要利用script标签不受跨域影响 通过回调函数接收数据)实际上是一个get请求

步骤

  • 准备一个回调函数(全局的)
  • 准备一个script标签链入对应的地址 传入对应的参数及回调函数
  • 加载完成 删除对应的script标签

设计模式

概述

设计模式是对应的一些处理方案形成的思想所构成的模式。主要是针对类和设计对象设计和构造的。它不区分语言,总共有23种设计模式(架构设计,源码设计)

设计模式的分类

  • 创建型模式(关于对象的创建)
  • 结构型模式(将多个小结构并入一个大结构)
  • 行为型模式(对象的通信逻辑)

设计模式分类图

设计模式七大原则

  • 单一责任原则
  • 开闭原则
  • 里氏置换原则
  • 依赖倒转原则
  • 接口隔离原则
  • 迪米特法则
  • 合成复用原则

主要讲解的模式

  •  创建型模式(工厂模式、单例模式)
  •  结构型模式(代理模式、装饰器模式、组合模式)
  •  行为型模式(观察者模式)

工厂者模式

以工厂的形式来生产对象(不关注对象的细节)

        function facotory(){
            // 创建对象
            let obj = {}
            // 属性赋值
            obj = Obj.name 
            // 返回对象
            return obj
        }

单例模式(饿汉、懒汉)

保证产生的对象只有一个(不会被污染)

利用闭包实现

        // 利用闭包实现 
        function singleton(){
            let single = null
        // 判断是否为null 是否需要重新创建
            return function(){
                if(!single){
                    single = new Object()
                }
                return single
            }
        }
        let singletonFn = singleton()
        var obj = singletonFn()
        var obj1 = singletonFn()
        console.log(obj === obj1)

利用原型实现

        // 原型实现
        function singletonPrototype(){
            // 判断原型上是否有这个对象
            if(!Object.prototype.single){
                Object.prototype.single = new Object()
            }
            return Object.prototype.single
        }
        var obj2 = singletonPrototype()
        var obj3 = singletonPrototype()
        console.log(obj2 === obj3)

利用静态属性实现

        // 利用静态属性
        function singleStatic(){
            if(!Object.single){
                Object.single = new Object()
            }
            return Object.single
        }
        var obj3 = singleStatic()
        var obj4= singleStatic()
        console.log(obj3 === obj4)

利用global对象实现

        // 使用global globalThis 指向当前global对象 window
        function singleGlobal(){
            if(!globalThis.single){
                globalThis.single = new Object()
            }
            return globalThis.single
        }
        var obj3 = singleGlobal()
        var obj4= singleGlobal()
        console.log(obj5 === obj6)

组合模式

将多个小结构合成一个大结构(将共有函数放在一起调用)

示例

        // 将多个小结构合成一个大结构
        function One(){
            this.init = function(){
                console.log('1')
            }
        }
        function Two(){
            this.init = function(){
                console.log('2')
            }
        }
        function Three(){
            this.init = function(){
                console.log('3')
            }
        }
        // 一个个调用 123
        new One().init()
        new Two().init()
        new Three().init()

将init方法 一起执行 利用组合模式来执行多个同名方法

        // 将init方法 一起执行 利用组合模式来执行多个同名方法
        function Combination(){
            this.objs = []
            // 传入对应的对象
            this.add = function(...objs){
                // 接收对应的对象数组
                this.objs = this.objs.concat([...objs])
            }
            // 执行对应的里面的init方法 以参数传递函数名的形式来执行
            this.exec = function(fnName){
                // 遍历对应的对象数组
                this.objs.forEach((obj)=>{
                    // 调用对应的方法
                    obj[fnName].call(this)
                })
            }
        }
        let combination = new Combination()
        combination.add(new One(),new Three())
        combination.exec('init') 

组合模式的应用 Vue里面use和install

    class Vue{
            // 解析对应的对象 执行对应的install
            static use(...objs){
                objs = objs.map(v=>{
                    // 如果没有install方法
                    if(!v.install){
                        if(typeof v != 'function'){
                            throw new Error('传入内容出错')
                        }
                        // 将本身当做install
                        let fn = v
                        v= {
                            install(){
                                fn()
                            }
                        }
                    }
                    return v
                })
                Vue.exec(objs)
            }
            // 传入对象进行执行
            static exec(arr){
                arr.forEach(obj => {
                    obj['install'].call(this.Vue)
                    
                });
            }
        }
        Vue.use({
            install(){
                console.log('吃饭吃饭')
            }
        },{
            install(){
                console.log('睡觉睡觉')
            }
        })
        Vue.use({
            install(vue){
                console.log(Vue)
                console.log('哈哈')
            }
        })

 装饰器模式

用一个新的类将对应的原本的对象进行包装再进行加强(在不改变原有对象的基础上增强对象)

        function Person() {
            this.run = function () {
                console.log('跑')
            }
        }
        //传入要增强的对象 返回一个新的对象
        function Stronger(person) {
            this.person = person
            this.run = function () {
                this.person.run()
                console.log('我会飞')
            }
        }
        //基础对象
        let person = new Person()
        person.run() //跑
        //增强的对象
        let stronger = new Stronger(person)
        stronger.run() //跑 我会飞 

 Ts内置有对应的装饰器 Decorator Ts中使用注解来进行对应的装饰器添加 @decorator

代理模式

概述代理模式是在原有对象的基础上增强对应的对象(利用代理对象来增强)代理对象通常访问的是实际的对象

注意事项

  • 代理对象对原本的对象进行了功能增强
  • 代理对象影响的是实际的对象

ES7新增对应的Proxy的类 来帮助我们进行代理

Proxy(vue3的底层实现)

实例化(传入对应的被代理对象 处理对象 产生一个代理对象)

var proxy = new Proxy(target,handler)

 示例

        var obj = {
            name : 'joe',
            age : 22
        }
        // 代理对象 传入被代理对象 及 处理对象
        // 在proxy里面的get set 不要使用proxy处理对象
        var proxy = new Proxy(obj,{
            // 获取相关的属性 被代理对象 属性名 代理对象
            get(targeObj,attrName,proxyObj){
                let result = targeObj[attrName]
                if(result == 'age'){
                    result += '岁'
                }else if(result == 'name'){
                    result = '我的名字叫'+result
                }
            },
            // 获取相关的属性 被代理对象 属性名 属性值 代理对象
            set(targeObj,attrName,attrValue,proxyObj){
                if(typeof attrValue != 'number' && attrName == 'age'){
                    throw new Error('你传入的不是一个数字')
                }
                return targeObj[attrName] = attrValue
            }
        })
        // 使用代理对象
        console.log(proxy.name) //访问get方法
        proxy.name = 'jack' //访问set方法
        console.log(proxy.name)
        // proxy.age = 'abc'
        console.log(obj.name)

proxy的handler相关属性和方法

观察者模式 

概述

观察者模式是前端最常用的模式,它相当于对应的监听和处理执行的机制。观察者模式别obServer又被称为发布者-订阅者模式。

常见的发布者订阅者模式

addEventListener (事件监听器)

        var box = document.querySelector('.box')
        // element.addEventListener(事件名,handler)
        box.addEventListener('click',function(){
            // 处理
            console.log('好看的一个盒子')
        })
  • 你 发布者 (box添加点击事件)
  • js事件处理线程 订阅者 (添加事件监听 保持监听)
  • 处理 处理函数 订阅者 (订阅者进行处理)

实现发布者订阅者模式

模仿eventListener来实现
事件监听 on

            // 监听事件传入一个事件名和对应的处理函数
            on(eventName, handler) {
                // 判断是否储存了对应的事件
                if (eventName in this.events) {
                    // 如果存储了就给他加到对应的处理函数数组内
                    this.events[eventName].add(handler)
                } else {
                    // 如果没有的话需要先开辟一个数组 将处理的函数装入
                    this.events[eventName] = new Set([handler])
                }
            }

事件执行 emit

            // 执行对应的处理函数 传入对应的事件执行对应的处理函数 传入对应的参数传递给处理函数
            emit(eventName, ...args) {
                // 如果不存在对应的事件 就退出
                if (!this.events[eventName]) {
                    return;
                }
                // 存在就遍历对应的集合 调用对应的处理函数
                this.events[eventName].forEach(handler => {
                    handler.apply(this, args)
                });
            }

事件取消 off

            // 移除事件监听器
            off(eventName, handler) {
                // 查询是否具备对应的事件
                if (!this.events[eventName]) {
                    return;
                }
                this.events[eventName].delete(handler)
            }

完整版实现

        class Observer {
            constructor() {
                //存储事件的容器和处理函数的容器{click:[handler],mousedown:[handler]}
                this.events = {}
            }
            // 监听事件传入一个事件名和对应的处理函数
            on(eventName, handler) {
                // 判断是否储存了对应的事件
                if (eventName in this.events) {
                    // 如果存储了就给他加到对应的处理函数数组内
                    this.events[eventName].add(handler)
                } else {
                    // 如果没有的话需要先开辟一个数组 将处理的函数装入
                    this.events[eventName] = new Set([handler])
                }
            }
            // 执行对应的处理函数 传入对应的事件执行对应的处理函数 传入对应的参数传递给处理函数
            emit(eventName, ...args) {
                // 如果不存在对应的事件 就退出
                if (!this.events[eventName]) {
                    return;
                }
                // 存在就遍历对应的集合 调用对应的处理函数
                this.events[eventName].forEach(handler => {
                    handler.apply(this, args)
                });
            }
            // 移除事件监听器
            off(eventName, handler) {
                // 查询是否具备对应的事件
                if (!this.events[eventName]) {
                    return;
                }
                this.events[eventName].delete(handler)
            }
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值