智慧园区前端技能

1.websocket

WebSocket 是一种在单个TCP 连接上进行全双工通信的协议。

  • 全双工通信:允许服务器和客户端在同一连接上同时、主动地发送和接收数据。

  • 持久连接:只需一次握手便可建立长久连接,无需每次数据传输都重新建立连接。

  • 低延迟与低开销:数据传输时不需要携带冗长的 HTTP 头部信息,WebSocket 的帧头部非常轻量(仅 2~14 字节),极大节省了带宽。

  • 二进制支持:除了文本,还能更轻松地处理二进制数据(如 ArrayBuffer)。

连接建立过程(握手)

WebSocket 并非直接建立连接,而是通过 HTTP 协议进行协议升级

  • 客户端发起一个标准的 HTTP GET 请求,请求头包含 Upgrade: websocket 和 Connection: Upgrade,以及一个随机生成的 Sec-WebSocket-Key。

  • 服务端如果支持,会返回 101 Switching Protocols 状态码,并在响应头中返回经过计算的 Sec-WebSocket-Accept 值。

  • 握手成功后,底层 TCP 连接保留,但应用层协议从HTTP切换为WebSocket

核心事件与 API

在浏览器端,WebSocket 对象提供了四个核心事件来管理连接生命周期:

  • onopen:连接成功建立时触发。

  • onmessage:接收到服务端推送的消息时触发。

  • onerror:发生通信错误时触发。

  • onclose:连接关闭时触发(需区分主动关闭和异常断开)。

  • 建连 :new WebSocket('ws://...')

  • 发消息 :ws.send('数据'),发送前一定要判断 ws.readyState === WebSocket.OPEN。

  • 收消息 :监听 ws.onmessage,数据在 event.data 里(通常是 JSON 字符串,需要 JSON.parse)。

  • 生命周期 :onopen(连上)、onclose(断开)、onerror(报错)

javascript 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>前端 WebSocket Demo</title>
</head>
<body>
  <h3>WebSocket 前端极简 Demo</h3>
  <input id="input" placeholder="输入消息..." />
  <button id="sendBtn">发送</button>
  <p>服务端回复:<span id="msg" style="color:blue;"></span></p>

  <script>
    // 1. 建立连接(替换为你实际的 ws 或 wss 地址)
    const ws = new WebSocket('ws://localhost:8080/ws');
    // 2. 连接成功
    ws.onopen = () => {
      console.log('✅ WebSocket 连接已建立');
    };
    // 3. 接收服务端消息
    ws.onmessage = (event) => {
      console.log('📩 收到消息:', event.data);
      document.getElementById('msg').innerText = event.data;
    };
    // 4. 点击按钮发送消息
    document.getElementById('sendBtn').onclick = () => {
      const input = document.getElementById('input');
      // 发送前最好判断一下连接状态,防止报错
      if (ws.readyState === WebSocket.OPEN) {
        ws.send(input.value);
        input.value = '';
      } else {
        console.warn('WebSocket 尚未连接');
      }
    };
    // 5. 连接关闭
    ws.onclose = () => {
      console.log('❌ WebSocket 连接已关闭');
    };
    // 6. 发生错误
    ws.onerror = (error) => {
      console.error('⚠️ WebSocket 发生错误:', error);
    };
  </script>
</body>
</html>

1.WebSocket 和 HTTP 的核心区别是什么?

  • HTTP 是单向的请求-响应模型,服务端无法主动推送;WebSocket 是全双工通信,双方都可以随时主动发消息。

  • HTTP通常是短连接(即使有 Keep-Alive 也是请求完即释放);WebSocket 是持久化的长连接。

  • 数据开销:HTTP 每次请求都要携带完整的 Header,开销大;WebSocket 建立连接后,数据帧头部极小,适合高频、小数据量的实时通信。

2.WebSocket 和 SSE (Server-Sent Events) 有什么区别?什么时候用谁?

  • 通信方向:SSE 是单向的(仅服务端向客户端推送),WebSocket 是双向的。

  • 协议与数据:SSE 基于 HTTP,通常只支持文本(JSON);WebSocket 是独立协议,支持文本和二进制。

  • 重连机制:SSE 内置了自动重连机制;WebSocket 需要开发者手动实现重连。

  • 场景选择:AI 流式输出、系统通知等只需服务端推送的场景用 SSE;实时聊天、在线游戏、协同编辑等需要双向交互的场景必须用 WebSocket。

3.如何保证 WebSocket 连接的稳定性?

  • 心跳检测 (Ping/Pong):由于网络波动或网关超时,长连接可能会"假死"。客户端需要定期(如 20-30 秒)发送 Ping 消息,服务端回复 Pong。如果连续多次未收到 Pong,则判定连接断开并主动关闭。

  • 断线重连策略:在 onerror 和 onclose 事件中触发重连。必须采用指数退避算法(如延迟 1s、2s、4s、8s 递增重试),并加入随机抖动,防止大量客户端同时重连导致服务器"雪崩"。

  • 状态恢复:重连成功后,必须重新发送 Token 进行身份验证,并重新订阅之前的频道或状态。

4.移动端或浏览器休眠时,WebSocket 断开怎么处理?

  • 可以利用 Page Visibility API 监听页面的可见性。当用户从后台切回前台(visibilitychange)时,检查连接状态,如果已断开则立即触发重连。

  • 结合 navigator.onLine 监听网络状态,在网络恢复时触发重连,避免在离线状态下发起无效请求。

5.ws 和 wss 的区别是什么?

  • ws:// 是明文传输,wss:// 是基于 TLS/SSL 加密的 WebSocket。生产环境强烈推荐使用 wss://,因为很多防火墙和代理会拦截未加密的 WebSocket 连接,且 wss 能防止数据被窃听或篡改。

2.微前端

qiankun是蚂蚁金服开源的一款微前端框架,基于 Single-SPA 进行了二次封装,提供了更完善的开箱即用体验。是目前国内最流行、最适合 Vue 生态的微前端方案之一,已在大量线上系统中经受过考验。

  • 主框架不限制接入应用的技术栈,子应用(React、Vue、Angular 等)具备完全自主权。

  • 微应用仓库独立,前后端可独立开发、部署,主框架自动完成同步更新。

  • 提供完备的JS沙箱和样式隔离机制,确保微应用间的样式和全局变量不相互影响。

  • 支持主子应用间的数据传递、全局状态管理,完整的应用加载、挂载、卸载生命周期

实现原理(面试高频考点)

  • HTML Entry 加载机制:qiankun 的加载入口不是一个JS文件,而是抓取子应用的index.html,解析其中的 <link>、<script> 等资源,再动态注入到基座页面中,使得子应用能像独立页面那样工作。

  • JS 沙箱隔离:

    • Proxy 沙箱:针对现代浏览器,对 window 的读写通过 Proxy 重定向到子应用私有对象,避免污染宿主全局。

    • 快照沙箱:针对兼容模式,进入子应用前保存全局状态,退出后恢复。

  • 样式隔离:

    • Strict 模式:基于 Shadow DOM,为每个微应用的容器包裹上一个 shadow dom 节点,实现浏览器原生的严格隔离。

    • 实验性模式(experimentalStyleIsolation):在运行时给 CSS 选择器加作用域前缀(类似 Scoped),限制其影响范围。

  • 路由劫持:监听浏览器的 hashchange 或 popstate 事件,根据 URL 匹配激活规则,自动卸载当前应用并挂载目标应用。

  1. 主子应用通信方案
  • Props 传递(父→子):主应用在注册或加载微应用时,通过 props 传递初始化数据(如用户信息、主题配置等),子应用在 mount 生命周期中接收。

  • 全局状态管理:通过 qiankun 提供的 initGlobalState API 实现跨应用的状态共享与监听。

  • 事件总线(Event Bus):基于 CustomEvent 实现微应用间的消息传递。

主应用(基座)配置:

javascript 复制代码
import { registerMicroApps, start } from 'qiankun';
// 注册子应用
registerMicroApps([
  {
    name: 'vue-app',        // 应用唯一名称
    entry: '//localhost:7100', // 子应用入口
    container: '#subapp-container', // 挂载容器
    activeRule: '/vue',      // 路由激活规则
    props: {                 // 传递给子应用的数据
      user: { name: '张三' }
    }
  }
]);
// 启动 qiankun
start({ 
  sandbox: { experimentalStyleIsolation: true }, // 开启实验性样式隔离
  prefetch: true // 开启预加载
});

子应用适配(以 Vue/React 为例):

子应用需要暴露生命周期钩子,并在挂载时将 DOM 渲染到主应用提供的容器中:

javascript 复制代码
// 子应用入口文件
export async function mount(props) {
  // 将应用挂载到 props.container 中
  ReactDOM.render(<App />, props.container);
}

export async function unmount(props) {
  // 卸载时清理 DOM
  ReactDOM.unmountComponentAtNode(props.container);
}
  1. JS 沙箱隔离原理

"在 qiankun 中,为了防止多个微应用同时运行时全局变量(如 window 对象)互相污染,它提供了 JS 沙箱机制。具体分为两种实现:

  • 第一种是快照沙箱(SnapshotSandbox):主要为了兼容不支持 Proxy 的老旧浏览器。它的原理是在微应用挂载前,对当前的 window 对象拍一张快照(浅拷贝)。微应用运行期间可以随意修改全局变量,但在卸载时,qiankun 会将当前的 window 状态与快照进行 Diff 对比,从而删除新增的属性、还原被修改的属性,实现环境恢复。

  • 第二种是代理沙箱(ProxySandbox):这是 qiankun 推荐的现代方案。它利用 ES6 的 Proxy 为每个微应用创建一个伪造的 fakeWindow 对象。微应用代码中对 window 的所有读写操作,都会被拦截并重定向到这个 fakeWindow 上,从而实现了真正的隔离。这种方式不仅性能更好,而且支持多个微应用同时运行(多实例)。"

  1. CSS 样式隔离原理

为了防止不同微应用的 CSS 样式互相覆盖,qiankun 提供了两种样式隔离方案:

  • 第一种是严格样式隔离(Strict Style Isolation):它基于 Web Components 的 Shadow DOM 技术。qiankun 会为每个微应用创建一个 Shadow Root,将子应用的 DOM 和样式包裹在里面。这种方式利用了浏览器原生的隔离特性,效果最好,但缺点是某些挂载到 document.body 的第三方 UI 组件(如弹窗、下拉框)可能会出现样式丢失的问题。

  • 第二种是实验性样式隔离(Scoped CSS):这也是目前更常用的方案。它的原理类似于 Vue 的 scoped 或 CSS Modules。qiankun 会在运行时拦截子应用的样式,给所有的 CSS 选择器动态添加一个带有应用名的属性前缀(例如 div[data-qiankun="app1"])。这样,样式的作用域就被严格限制在了该子应用的容器内部,既实现了隔离,又避免了 Shadow DOM 的兼容性问题。"

在实际项目中,通常会在主应用启动时配置 experimentalStyleIsolation: true 来开启运行时 CSS 隔离,因为它对现有项目的侵入性最小。如果遇到第三方组件样式错乱的问题,结合全局 CSS 变量或给主应用样式加前缀来兜底处理。

3.Three.js

Three.js 是一个基于JS编写的开源3D 图形库(3D引擎)。

核心作用是让前端开发者能够直接在网页浏览器中,轻松创建和展示复杂的、逼真的 3D 场景和动画,完全不需要用户安装任何插件

解决了什么痛点?(与 WebGL 的关系)

在浏览器里画 3D 图形,底层依赖的是 WebGL 技术。直接使用原生WebGL极其繁琐,需要处理大量复杂的图形学细节(如着色器、顶点缓冲、矩阵运算等),学习门槛极高。

Three.js 就像是一个"翻译官"和"工具箱",它封装了 WebGL 的底层复杂性,提供了一套极其简洁、优雅的JS API。只需要几行代码,就能调用 GPU 实现原本需要成百上千行代码才能完成的 3D 渲染效果。

核心"三剑客"是什么?

任何一个 Three.js 3D 场景的搭建,都离不开这三个最核心的概念:

  • 场景Scene:相当于一个虚拟的3D舞台或容器,里面放置了所有的3D物体、灯光等。

  • 相机Camera:相当于观察者的眼睛。决定了从什么角度、什么视野去观察这个 3D 舞台(最常用的是模拟人眼"近大远小"的透视相机)。

  • 渲染器 Renderer:相当于摄影师。负责将场景和相机捕捉到的信息,最终计算并绘制到网页的Canvas画布上,让能看到 3D 画面

在前端开发中有什么用?

数字孪生与 3D 可视化:在网页上 1:1 还原真实的园区、工厂或城市,展示设备运行状态、安防监控热力图等。

WebGIS 进阶:与 Cesium 等地图引擎结合,在真实的 3D 地球上叠加建筑白模、粒子特效、无人机巡检轨迹等。

数据大屏:将枯燥的数据转化为立体的3D图表,如3D柱状图、地球飞线等,提升视觉冲击力

互动式展示:如网页端的 3D 汽车预览、虚拟展厅、在线 3D 小游戏等。

  1. 构建一个最基础的3D场景,必须掌握以下三个核心类的构造函数:
  • new THREE.Scene():创建场景对象,它是所有 3D 物体、光源和相机的根容器

  • new THREE.PerspectiveCamera():创建透视相机,参数通常包括视野角度(FOV)、宽高比(Aspect)、近裁剪面(Near)和远裁剪面(Far)。

  • new THREE.WebGLRenderer({}):创建 WebGL 渲染器,负责将场景和相机渲染到 HTML 的 Canvas 画布上

  1. 物体构建 API(几何体 + 材质)

3D 场景中的可见物体(网格 Mesh)由几何体和材质两部分组合而成:

  • 几何体 API (Geometry):定义物体的形状。最常用的是 new THREE.BoxGeometry(宽, 高, 深) 创建立方体,此外还有 SphereGeometry(球体)、CylinderGeometry(圆柱)等。

  • 材质 API (Material):定义物体的外观。最基础的是 new THREE.MeshBasicMaterial({color: 0xff0000})(不受光照影响的基础材质);支持物理光照渲染的则是 new THREE.MeshStandardMaterial({...})。

  • 网格组合 API:new THREE.Mesh(geometry, material),将几何体和材质组合成一个可渲染的网格对象。

  1. 场景图操作 API

用于管理场景中的对象层级和空间变换:

  • scene.add(object):将相机、灯光、网格等对象添加到场景中,这是最常用的场景管理方法。

  • 空间变换属性:

    • object.position.set(x, y, z):设置物体在 3D 空间中的位置。

    • object.rotation.set(x, y, z):设置物体的旋转角度(以弧度为单位)。

    • object.scale.set(x, y, z):设置物体的缩放比例。

  1. 渲染与动画 API

让静态的 3D 场景动起来:

  • renderer.render(scene, camera):执行一次渲染,将当前场景通过指定相机的视角绘制到屏幕上。

  • requestAnimationFrame(callback):浏览器原生 API,Three.js 依赖它来实现渲染循环(动画循环),确保动画以流畅的帧率(如 60FPS)持续更新和重绘。

  1. 交互与辅助 API

提升用户体验和开发调试效率:

  • OrbitControls:轨道控制器插件。通过监听鼠标事件,允许用户按住左键旋转视角、滚轮缩放、按住右键平移,是 3D 预览最常用的交互 API。

  • THREE.AxesHelper(size):坐标轴辅助对象。在场景中添加红(X轴)、绿(Y轴)、蓝(Z轴)三色坐标线,方便开发者定位和调试 3D 空间

4.WebGIS

Web地理信息系统的核心公式为:WebGIS = GIS基础理论 + Web前端开发 + 可视化技术

  1. GIS 基础理论(必学基石)
  • 坐标系与投影:这是WebGIS的灵魂。必须掌握地理坐标系(如 WGS84、CGCS2000)与投影坐标系(如 Web Mercator)的区别。了解国内常见的坐标系(如高德的 GCJ-02、百度的 BD-09)以及它们之间的转换。

  • 空间数据类型:理解矢量数据(点、线、面)和栅格数据(瓦片、遥感影像)的区别与渲染逻辑

  • 地理数据格式:必须一眼看懂并能处理 GeoJSON 格式,了解 Shapefile、KML、3D Tiles 等格式

  • OGC 地图服务:掌握 WMS(地图服务)、WMTS(瓦片服务)、WFS(矢量要素服务)的调用方式与区别

  1. 前端地图技术栈
  • 二维地图库:

    • Leaflet:轻量、简单,适合基础展示和移动端。

    • OpenLayers:功能极其强大,支持专业GIS业务,政企项目首选。

    • Mapbox GL JS:基于 WebGL,支持矢量瓦片,适合炫酷的定制化商业可视化。

  • 三维地图库:

    • CesiumJS:Web 3D GIS 的行业标准,支持真实地形、BIM模型、3D Tiles,是智慧城市和数字孪生的核心引擎。
  1. 进阶与性能优化
  • 海量数据渲染:掌握聚合点(Cluster)、分级加载、数据分页、Web Worker 多线程处理等技术,解决页面卡顿和崩溃问题。

  • 空间分析:了解缓冲区分析、叠加分析、路径规划、地理编码(地址转坐标)等前端实现方案。

  • 后端 GIS 能力(加分项):了解 PostGIS(空间数据库)、GeoServer(地图服务发布)的基本原理。

1.什么是 WebGIS?它和传统 GIS 有什么区别?

传统 GIS 偏向桌面端,侧重数据采集、建模和空间分析;而 WebGIS 侧重于通过浏览器展示地图、数据可视化和空间数据接口调用,技术栈以 JavaScript、WebGL 和前端框架为主。

2.如何处理不同坐标系的地理数据?

可以使用地图库自带的坐标转换功能,或者引入第三方库(如 proj4.js)将不同坐标系(如 WGS84、GCJ-02)统一转换为地图引擎所需的坐标系,避免点位偏移。

3.WebGIS 中如何处理大规模地理数据的渲染性能问题?

  1. 数据层:采用分级加载、数据分页、按需请求;2. 渲染层:使用聚合图层(Cluster)、LOD(多细节层次)算法、动态渲染;3. 交互层:使用异步操作和 Web Worker,避免阻塞主线程。

4.介绍一下你熟悉的 GIS 地图库及其特点?

OpenLayers:它功能强大,支持多种地图数据源,可定制性极高,适合复杂的企业级 WebGIS 业务;或者 Cesium:它是真三维地球,擅长处理 3D Tiles、倾斜摄影模型,是数字孪生场景的首选

5.WMS 和 WMTS 服务有什么区别?

WMS(动态地图服务)是客户端请求时,服务端实时渲染生成地图图片返回,灵活性高但性能差;WMTS(瓦片地图服务)是服务端预先将地图切割成固定大小的图块(金字塔),客户端按需请求,加载速度极快,适合大规模底图展示。

6.Cesium 中的 Entity 和 Primitive 有什么区别?

Entity 是高层 API,使用简单,支持丰富的样式和交互,但底层封装深,加载海量数据时性能较差;Primitive 是底层 API,直接面向图形渲染,性能极高,适合加载成千上万个模型或粒子效果,但代码编写复杂。

入门学习路线

  • 阶段 1:GIS 基础理论打底

    • 搞懂坐标系、投影、矢量/栅格数据。

    • 学习使用 QGIS 等开源工具进行简单的空间数据查看和处理。

  • 阶段 2:巩固 Web 前端基础

    • 熟练掌握 JavaScript (ES6+)、Vue 或 React。

    • 理解前端工程化(Webpack/Vite)和状态管理。

  • 阶段 3:攻克 WebGIS 核心框架(重点)

    • 先学 Leaflet 或 OpenLayers(二维),跑通 GeoJSON 渲染、鼠标交互(测距、点击查询)等基础功能。

    • 再学 Cesium(三维),掌握三维场景搭建、3D Tiles 模型加载、相机控制等。

  • 阶段 4:项目实战与进阶

    • 找一个开源项目(如智慧园区、交通轨迹可视化)从 0 到 1 完整实现。

    • 学习空间数据库(PostGIS)和地图服务发布GeoServer,打通前后端 GIS 闭环

相关推荐
计算机魔术师8 小时前
管谷歌的不是Pichai一个人,是一整层AI智能体
前端
米米商聊8 小时前
图标能点,按钮就可用了吗?键盘、名称与收藏状态
前端·javascript
Younglina9 小时前
三个晚上,我和 WorkBuddy 做了个生图网站
前端·后端·ai编程
xy34539 小时前
Axure 9.0 内联框架加载方式
前端·ui·html·axure·原型·产品设计
陈随易10 小时前
副业搞钱点子之收入查看器
前端·后端
Profile排查笔记10 小时前
浏览器指纹逆向怎么分析:从网络请求追踪到 JavaScript 采集链
前端·人工智能·后端·自动化
hudie76510 小时前
LikeShop 二开最常改的 5 个文件(附改前改后对比)
前端·uni-app·php·个人开发
qetfw11 小时前
Bash 函数与流程控制:read、if、for、case 验证
linux·前端·javascript·bash
鬼手点金11 小时前
从 API 消息到模型 Token:Chat Template
java·前端·javascript·数据库·人工智能·深度学习·1024程序员节
Shadow(⊙o⊙)11 小时前
LangChain 自定义工具全解析:从 @tool 到 bind_tools 的完整调用链路
java·服务器·前端·1024程序员节