前端开发之代理模式
介绍
代理模式是一种结构型设计模式,它通过为一个对象提供一个代理对象来控制对该对象的访问。代理对象可以在访问真实对象之前或之后添加一些额外的操作。
class RealImg {
fileName: string;
constructor(fileName: string) {
this.fileName = fileName;
}
disPlay() {
this.loadFromDist()
console.log("disPlay:", this.fileName)
}
private loadFromDist(){
console.log("loading:", this.fileName)
}
}
class ProxyImg{
realImg: RealImg
constructor(fileName: string) {
this.realImg = new RealImg(fileName)
}
display(){
this.realImg.disPlay()
}
}
const proxyImg = new ProxyImg('xxx.png')
proxyImg.display()
// loading: xxx.png
// disPlay: xxx.png
符合设计原则:
- 代理和目标分离,解耦
- 代理可自行扩展
- 目标也可自行扩展
场景
(1)DOM事件代理(委托)
事件绑定到父容器上,而非目标节点。适合目标较多或者数量不确定(入无限加载的瀑布流图片列表)
<div id="container">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
</div>
const container = document.getElementById("container");
if (container) {
// DOM 事件代理(委托)
container.addEventListener("click", (event) => {
const target = event.target as Element;
if (target.nodeName === "A") {
alert(target.innerHTML);
}
});
}
(2)webpack devServer proxy
正向代理(客户端代理)。开发环境,前端请求服务器 API,代理本地服务器,或者 mock 接口。
编辑vite.config.ts
server: {
port: 3000,
proxy: {
"/api": {
target: "http://localhost:8888",
/** 是否启用websockets */
ws: true,
/** 是否允许跨域 */
changeOrigin: true
}
},
}
编辑 index.ts
<script lang="ts" setup>
import { onMounted } from "vue";
import axios from "axios";
onMounted(() => {
document.getElementById("btn1")?.addEventListener("click", () => {
axios.get("/api/getInfo").then((res) => {
console.log("res", res);
});
});
});
</script>
<template>
<div id="container">
<button id="btn1">发送请求</button>
</div>
</template>
编辑服务 server.js 文件,执行 node server.js
import http from "http";
http
.createServer(function (req, res) {
if (req.url === "/api/getInfo") {
res.end("info");
} else {
res.end("hello");
}
})
.listen(8888);
启动前端服务后,访问 http://localhost:3000 点击“发送请求”
(3)Nginx 反向代理(服务端代理)
1. 将上述 vite+typescript 前端项目打包成 dist(vite.config.ts 配置 base: "dist"),放入nginx的 www 目录。
2. 配置nginx
server {
listen 8080;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /api {
proxy_pass http://127.0.0.1:8888;
}
}
3. 启动 nginx
> brew services start nginx
==> Successfully started `nginx` (label: homebrew.mxcl.nginx)
4. 控制台执行 node server.js,启动上述 server.js 文件。
5. 页面访问 http://localhost:8080/dist