最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 『面试的底气』—— 设计模式之代理模式(一)|8月更文挑战

    正文概述 掘金(红尘炼心)   2021-08-12   534

    这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

    前言

    在面试高级前端时,往往会遇到一些关于设计模式的问题,每次都回答不太理想。恰逢8月更文挑战的活动,准备用一个月时间好好理一下关于设计模式方面的知识点,给自己增加点面试的底气。

    定义

    关键

    代理模式的关键是,当程序不方便或者不满足需要去直接访问一个对象的时候,提供一个替身 对象来控制对这个对象的访问,程序实际上访问的是替身对象。替身对象对请求做出一些处理之 后,再把请求转交给本体对象。

    JavaScript中的代理模式

    代理模式的变体种类非常多,不一定都适合在JavaScript中使用,本文挑两种在JavaScript开发中最常用的两种代理来介绍,分别是虚拟代理和缓存代理。

    虚拟代理

    虚拟代理会把一些开销很大的对象,延迟到真正需要它的时候才去创建。这里用实现图片预加载功能的例子来介绍虚拟代理。

    图片预加载是一种常用的技术,如果直接给某个 img 标签节点设置 src 属性,由于图片过大或者网络不佳,图片的位置往往有段时间会是一片空白。常见的做法是先用一张 loading 图片占位,然后用异步的方式加载图片,等图片加载好了再把它填充到 img 节点里,这种场景就很适合使用虚拟代理。

    先创建一个MyImage类,用来生成一个 img 节点并将插入 body 中。

    class MyImage {
      constructor() {
        this.img = document.createElement('img');
        document.body.appendChild(this.img);
      }
      setSrc(src) {
        this.img.src = src;
      }
    }
    

    执行const myImage = new MyImage()生成一个 img 节点并将插入 body 中,先在开发者工具中把网速调至Slow 3G,然后通过 执行myImage.setSrc('xxx')给该 img 节点设置 src 属性,可以看到,在图片被加载好之前,页面中有段时间会是一片空白。

    为了解决这个问题。写一个代理类ProxyImage,通过这个代理类,实现在图片被真正加载好之前,页面中将出现一张 loading 图片占位, 来提示用户图片正在加载。

    class ProxyImage {
      constructor() {
        this.myImage = new MyImage();
        this.image = new Image();
        this.image.onload = function () {
          this.myImage.setSrc(this.image.src);
        }
      }
      setSrc(src) {
        this.myImage.setSrc('./loading.gif');
        this.image.src = src;
      }
    }
    const proxyImage = new ProxyImage();
    proxyImage.setSrc(xxxx);
    

    通过ProxyImage代理类间接地访问MyImage类实例化生成的对象,ProxyImage类控制了对MyImage类实例化生成的对象访问,并且在此过程中加入一些额外的操作,比如在真正的图片加载好之前,先把 img 节点的 src 设置为一张本地的 loading 图片。

    执行proxyImage.setSrc(xxxx)后,会先执行this.myImage.setSrc('./loading.gif')给 img 节点的src 属性设置一张 loading 占位图的地址,同时把真正要展示的图片地址 xxxx 赋值给new Image()创建的图片对象的 src 属性,在图片对象加载成功后再把图片地址 xxxx 通过this.myImage.setSrc(this.image.src)重新赋值给 img 节点的 src 属性。

    这样在真正要展示的图片加载成功之前,由MyImage类实例化生成的 img 节点会一直展示 loading 的占位图,实现图片预加载的功能。

    代理的意义

    假如不用虚拟代理可以实现图片预加载的功能吗,当然可以,下面来实现一下:

    class MyImage {
      constructor() {
        this.img = document.createElement('img');
        document.body.appendChild(this.img);
        this.image = new Image();
        image.onload = function () {
          this.img.src = this.image.src;
        };
      }
      setSrc(src) {
        this.img.src = './loading.gif';
        this.image.src = src;
      }
    }
    

    咋看一下代码量还更少,代码更简单了。但是这么写违背了设计模式的单一职责原则,在MyImage类中除了负责生成 img 节点并设置src,还要负责预加载图片。

    假如有一张图片非常小,根本不需要预加载,使用预加载还会出现占位图一闪而过的问题。那怎么办呢?难道要重新写个MyImage类,这会违背开放—封闭原则

    实际上MyImage类的功能只需要给 img 节点设置 src,预加载图片只是一个锦上添花的功能。假如把这个功能放在代理中,那么代理的作用在这里就体现出来了,代理负责预加载图片,预加载的操作完成之后,重新交给MyImage类中来给 img 节点设置 src 。

    这里并没有改变或者增加 MyImage 的功能,只是通过代理,给MyImage类添加了新的功能。这是符合开放—封闭原则

    给 img 节点设置 src 和图片预加载这两个功能,被隔离在两个类里,它们可以各自变化而不影响对方。何况就算有一天我们不再需要预加载,那么只需要改成请求本体而不是请求代理对象即可。


    起源地下载网 » 『面试的底气』—— 设计模式之代理模式(一)|8月更文挑战

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元