本章讲一个结构型设计模式-代理模式( Proxy Pattern )
定义
为一个对象提供一种代理以便控制对它的访问, 就是增加了一种访问方式, 比如某一个花销很大的动作, 可以通过按需加载的方式, 等用到它再去创建
代理模式也分很多种, 下面图也只是列了一部分, 我挑几个前端常用的、并且我了解的写一写
graph TD
代理模式 --> 远程代理
代理模式 --> 虚拟代理
代理模式 --> 缓存代理
代理模式 --> 保护代理
代理模式 --> 智能引用代理
虚拟代理
前端比较常用的虚拟代理比如图片懒加载、预加载 (有些人把这两混淆了), 这里举个预加载例子吧, 比如支付宝饿了吗外卖 经常有那个刮卡或者翻牌红包, 这种情况就可以用预加载
//创建三张卡牌
<div class="card-box" @click="handleClick">
<img :src="src" data-src="~D:/文章图片/hbmz.png" >
<img :src="src" data-src="~D:/文章图片/hbmz.png" >
<img :src="src" data-src="~D:/文章图片/hbmz.png" >
</div>
//这里直接预加载几张抽奖结果图片, 但是不让它显示, 待会用这里的图片替换用户点击的那张卡牌
//实际情况这里不止一张, 需要预加载所有翻牌结果图, 这里只是拿一张举例
<img id="img" src="~D:/文章图片/hbmz.png" style="display: none">
暗度陈仓
class IM {
constructor(img) {
this.img = img
}
replace(src) {
this.img.src = src
}
}
function handleClick(e) {
const preload = document.getElementById('img')
new IM( e.target ).replace( preload.src )
}
缓存代理
前端经典的缓存代理 - 阶乘
function factorial(n) {
console.log('重新计算阶乘')
if (n < 2) {
return n
} else {
return n * factorial(n-1)
}
}
factorial(3)
factorial(3)
//这样执行两次就会打印 2 * 3 次
有时候我们不想每次重新计算阶乘, 这时候我们添加下缓存
function factorial(n) {
console.log('重新计算阶乘')
if (n < 2) {
return n
} else {
return n * factorial(n-1)
}
}
function proxy(fn) {
const catchObject = {}
return function(key) {
if (key in catchObject) {
return catchObject[key]
} else {
return catchObject[key] = fn(key)
}
}
}
const instance = proxy(factorial)
instance(3)
instance(3)
instance(3)
//这时候我们发现无论 “重复” 执行多少次, 都只计算了一次
前端经典的缓存代理 - tab
<div class="tab" onClick="handleClick">
<span> 1 </span>
<span> 2 </span>
<span> 3 </span>
</div>
<div class="content">
<!-- 根据tab获取不同数据显示在这 -->
</div>
class ProxyTab {
static catch = {}
constructor(target) {
if (!ProxyTab.catch[target]) {
ProxyTab.catch[target] = this.http()
}
}
http() {
return axios.get('xxx')
}
}
function handleClick(e) {
new ProxyTab(e.target)
}
类似场景还有分页、事件代理(ul代理li事件), 这次就先写这么多了
最后的轻语
开始并完成一件事情, 比做好它更重要。
因为只要开始了, 你就有机会把它做得更好
“现在” 就是最好的时机
不管怎样, 只要开始就好