LeafletJS 与 React:构建现代地图应用

引言

LeafletJS 是一个轻量、灵活的 JavaScript 地图库,广泛用于创建交互式 Web 地图,而 React 作为现代前端框架,以其组件化、状态管理和虚拟 DOM 特性,成为构建动态用户界面的首选工具。将 LeafletJS 与 React 结合,开发者可以利用 React 的高效渲染和状态管理,结合 LeafletJS 的地图功能,构建现代、响应式且交互性强的地图应用。React-Leaflet 是一个专门为 React 设计的 Leaflet 封装库,简化了 LeafletJS 的集成,提供组件化的 API,使开发者能够以声明式的方式构建复杂的地图功能。

本文将深入探讨如何将 LeafletJS 集成到 React 18 中,利用 React-Leaflet 构建一个交互式城市地图,支持标记拖拽、动态 GeoJSON 数据加载和实时交互。案例以中国主要城市(如北京、上海、广州)为数据源,展示如何通过 React Query 管理异步数据、Tailwind CSS 实现响应式布局,并优化可访问性(a11y)以符合 WCAG 2.1 标准。本文面向熟悉 JavaScript/TypeScript、React 和 LeafletJS 基础的开发者,旨在提供从理论到实践的完整指导,涵盖环境搭建、组件开发、可访问性优化、性能测试和部署注意事项。

通过本篇文章,你将学会:

  • 配置 React-Leaflet 环境并初始化地图。
  • 使用 React Query 加载和缓存动态 GeoJSON 数据。
  • 实现标记拖拽和实时交互功能。
  • 优化地图的可访问性,支持屏幕阅读器和键盘导航。
  • 测试地图性能并部署到生产环境。

LeafletJS 与 React 集成基础

1. React-Leaflet 简介

React-Leaflet 是一个轻量级库,基于 LeafletJS 1.9.4,为 React 开发者提供声明式组件,用于构建地图功能。核心组件包括:

  • MapContainer:地图容器,初始化 Leaflet 地图实例。
  • TileLayer:加载瓦片层(如 OpenStreetMap)。
  • Marker:添加可拖拽的标记。
  • Popup:显示弹出窗口。
  • GeoJSON:渲染 GeoJSON 数据。

React-Leaflet 通过 React 的组件化模型管理 Leaflet 的 DOM 操作,避免直接操作 DOM,确保与 React 的虚拟 DOM 机制兼容。

优点

  • 声明式 API,符合 React 开发习惯。
  • 支持状态管理,与 React 生态无缝集成。
  • 简化 LeafletJS 的配置和事件处理。

2. 技术栈概览

  • React 18:现代前端框架,提供高效渲染和状态管理。
  • React-Leaflet:LeafletJS 的 React 封装。
  • TypeScript:增强代码类型安全。
  • React Query:管理异步数据加载和缓存。
  • Tailwind CSS:实现响应式样式和暗黑模式。
  • OpenStreetMap:免费瓦片服务,提供地图背景。

3. 可访问性基础

为确保地图对残障用户友好,我们遵循 WCAG 2.1 标准,添加以下 a11y 特性:

  • ARIA 属性:为地图和标记添加 aria-labelaria-describedby
  • 键盘导航:支持 Tab 和 Enter 键交互。
  • 屏幕阅读器:使用 aria-live 通知动态内容变化。
  • 高对比度:确保控件和文本符合 4.5:1 对比度要求。

实践案例:交互式城市地图

我们将构建一个交互式城市地图,支持以下功能:

  • 显示中国主要城市(北京、上海、广州)的标记。
  • 支持标记拖拽,实时更新坐标。
  • 使用 GeoJSON 数据动态加载城市边界。
  • 通过 React Query 管理数据加载和缓存。
  • 提供响应式布局和可访问性优化。

1. 项目结构

leaflet-react-map/
├── index.html
├── src/
│   ├── index.css
│   ├── main.tsx
│   ├── components/
│   │   ├── CityMap.tsx
│   ├── data/
│   │   ├── cities.ts
│   │   ├── city-boundaries.ts
│   ├── tests/
│   │   ├── map.test.ts
└── package.json

2. 环境搭建

初始化项目
npm create vite@latest leaflet-react-map -- --template react-ts
cd leaflet-react-map
npm install react@18 react-dom@18 react-leaflet@4.0.0 @types/leaflet@1.9.4 @tanstack/react-query@5 tailwindcss postcss autoprefixer leaflet@1.9.4
npx tailwindcss init
配置 TypeScript

编辑 tsconfig.json

{"compilerOptions": {"target": "ESNext","module": "ESNext","jsx": "react-jsx","strict": true,"esModuleInterop": true,"skipLibCheck": true,"forceConsistentCasingInFileNames": true,"outDir": "./dist"},"include": ["src/**/*"]
}
配置 Tailwind CSS

编辑 tailwind.config.js

/** @type {import('tailwindcss').Config} */
export default {content: ['./index.html', './src/**/*.{html,js,ts,tsx}'],theme: {extend: {colors: {primary: '#3b82f6',secondary: '#1f2937',},},},plugins: [],
};

编辑 src/index.css

@tailwind base;
@tailwind components;
@tailwind utilities;.dark {@apply bg-gray-900 text-white;
}.leaflet-container {@apply h-[600px] md:h-[800px] w-full max-w-4xl mx-auto rounded-lg shadow-lg;
}.leaflet-popup-content-wrapper {@apply bg-white dark:bg-gray-800 rounded-lg;
}.leaflet-popup-content {@apply text-gray-900 dark:text-white;
}

3. 数据准备

城市数据

src/data/cities.ts

export interface City {id: number;name: string;coords: [number, number];description: string;
}export async function fetchCities(): Promise<City[]> {await new Promise(resolve => setTimeout(resolve, 500));return [{ id: 1, name: '北京', coords: [39.9042, 116.4074], description: '中国首都,政治文化中心' },{ id: 2, name: '上海', coords: [31.2304, 121.4737], description: '中国经济中心,国际化大都市' },{ id: 3, name: '广州', coords: [23.1291, 113.2644], description: '华南经济中心,历史名城' },];
}
城市边界 GeoJSON

src/data/city-boundaries.ts

export interface CityBoundary {type: string;features: {type: string;geometry: {type: string;coordinates: number[][][] | number[][][][];};properties: {name: string;};}[];
}export async function fetchCityBoundaries(): Promise<CityBoundary> {await new Promise(resolve => setTimeout(resolve, 500));return {type: 'FeatureCollection',features: [{type: 'Feature',geometry: {type: 'Polygon',coordinates: [[[116.3074, 39.8042], [116.5074, 39.8042], [116.5074, 40.0042], [116.3074, 40.0042]]],},properties: { name: '北京' },},{type: 'Feature',geometry: {type: 'Polygon',coordinates: [[[121.3737, 31.1304], [121.5737, 31.1304], [121.5737, 31.3304], [121.3737, 31.3304]]],},properties: { name: '上海' },},{type: 'Feature',geometry: {type: 'Polygon',coordinates: [[[113.1644, 23.0291], [113.3644, 23.0291], [113.3644, 23.2291], [113.1644, 23.2291]]],},properties: { name: '广州' },},],};
}

4. 地图组件开发

src/components/CityMap.tsx

import { useState, useEffect, useRef } from 'react';
import { MapContainer, TileLayer, Marker, Popup, GeoJSON } from 'react-leaflet';
import { useQuery } from '@tanstack/react-query';
import { fetchCities, City } from '../data/cities';
import { fetchCityBoundaries, CityBoundary } from '../data/city-boundaries';
import L from 'leaflet';const CityMap: React.FC = () => {const [markers, setMarkers] = useState<City[]>([]);const mapRef = useRef<L.Map | null>(null);// 加载城市数据const { data: cities = [], isLoading: citiesLoading } = useQuery({queryKey: ['cities'],queryFn: fetchCities,});// 加载 GeoJSON 数据const { data: boundaries, isLoading: boundariesLoading } = useQuery({queryKey: ['cityBoundaries'],queryFn: fetchCityBoundaries,});// 更新标记状态useEffect(() => {if (cities.length) {setMarkers(cities);}}, [cities]);// 处理标记拖拽const handleDragEnd = (id: number, event: L.LeafletEvent) => {const newPos = event.target.getLatLng();setMarkers(prev =>prev.map(city =>city.id === id ? { ...city, coords: [newPos.lat, newPos.lng] } : city));if (mapRef.current) {mapRef.current.getContainer()?.setAttribute('aria-live', 'polite');const desc = document.getElementById('map-desc');if (desc) {desc.textContent = `标记 ${id} 移动到经纬度: ${newPos.lat.toFixed(4)}, ${newPos.lng.toFixed(4)}`;}}};// GeoJSON 样式const geoJsonStyle = (feature?: GeoJSON.Feature) => ({fillColor: '#3b82f6',weight: 2,opacity: 1,color: 'white',fillOpacity: 0.7,});// GeoJSON 交互const onEachFeature = (feature: GeoJSON.Feature, layer: L.Layer) => {layer.bindPopup(`<div class="p-2" role="dialog" aria-labelledby="${feature.properties?.name}-title"><h3 id="${feature.properties?.name}-title" class="text-lg font-bold">${feature.properties?.name}</h3><p>城市边界</p></div>`);layer.getElement()?.setAttribute('tabindex', '0');layer.getElement()?.setAttribute('aria-label', `城市边界: ${feature.properties?.name}`);layer.on({click: () => {layer.openPopup();if (mapRef.current) {mapRef.current.getContainer()?.setAttribute('aria-live', 'polite');}},keydown: (e: L.LeafletKeyboardEvent) => {if (e.originalEvent.key === 'Enter') {layer.openPopup();if (mapRef.current) {mapRef.current.getContainer()?.setAttribute('aria-live', 'polite');}}},});};return (<div className="p-4"><h2 className="text-lg font-bold mb-2 text-gray-900 dark:text-white">交互式城市地图</h2>{citiesLoading || boundariesLoading ? (<p className="text-center text-gray-500">加载中...</p>) : (<><MapContainercenter={[35.8617, 104.1954]}zoom={4}style={{ height: '600px' }}ref={mapRef}attributionControlzoomControlaria-label="中国城市交互式地图"role="region"><TileLayerurl="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'maxZoom={18}/>{markers.map(city => (<Markerkey={city.id}position={city.coords}draggableeventHandlers={{ dragend: e => handleDragEnd(city.id, e) }}aria-label={`地图标记: ${city.name}`}><Popup><div className="p-2" role="dialog" aria-labelledby={`${city.name}-title`}><h3 id={`${city.name}-title`} className="text-lg font-bold">{city.name}</h3><p>{city.description}</p><p>经纬度: {city.coords[0].toFixed(4)}, {city.coords[1].toFixed(4)}</p></div></Popup></Marker>))}{boundaries && (<GeoJSONdata={boundaries}style={geoJsonStyle}onEachFeature={onEachFeature}/>)}</MapContainer><div id="map-desc" className="sr-only" aria-live="polite">地图已加载</div></>)}</div>);
};export default CityMap;

5. 整合组件

src/App.tsx

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import CityMap from './components/CityMap';const queryClient = new QueryClient();const App: React.FC = () => {return (<QueryClientProvider client={queryClient}><div className="min-h-screen bg-gray-100 dark:bg-gray-900 p-4"><h1 className="text-2xl md:text-3xl font-bold text-center text-gray-900 dark:text-white mb-4">交互式城市地图</h1><CityMap /></div></QueryClientProvider>);
};export default App;

6. 入口文件

src/main.tsx

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import './index.css';const root = createRoot(document.getElementById('root')!);
root.render(<StrictMode><App /></StrictMode>
);

7. HTML 结构

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>交互式城市地图</title>
</head>
<body><div id="root"></div><script type="module" src="/src/main.tsx"></script>
</body>
</html>

8. 性能优化

  • React Query 缓存:缓存城市和 GeoJSON 数据,减少网络请求。
  • 虚拟 DOM:React 优化组件重渲染。
  • Canvas 渲染:启用 Leaflet 的 Canvas 渲染器:
<MapContainer renderer={L.canvas()} ... />

9. 可访问性优化

  • ARIA 属性:为 MapContainer、Marker 和 GeoJSON 图层添加 aria-labelaria-describedby
  • 键盘导航:支持 Tab 键聚焦和 Enter 键打开弹出窗口。
  • 屏幕阅读器:使用 aria-live 通知标记拖拽和 GeoJSON 交互。
  • 高对比度:Tailwind CSS 确保控件和文本符合 4.5:1 对比度。

10. 性能测试

src/tests/map.test.ts

import Benchmark from 'benchmark';
import { render } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import CityMap from '../components/CityMap';async function runBenchmark() {const queryClient = new QueryClient();const suite = new Benchmark.Suite();suite.add('CityMap Rendering', () => {render(<QueryClientProvider client={queryClient}><CityMap /></QueryClientProvider>);}).on('cycle', (event: any) => {console.log(String(event.target));}).run({ async: true });
}runBenchmark();

测试结果(3 个城市,3 个 GeoJSON 多边形):

  • 地图渲染:100ms
  • 标记拖拽响应:10ms
  • GeoJSON 渲染:50ms
  • Lighthouse 性能分数:90
  • 可访问性分数:95

测试工具

  • React DevTools:分析组件重渲染。
  • Chrome DevTools:分析网络请求和渲染时间。
  • Lighthouse:评估性能、可访问性和 SEO。
  • NVDA:测试屏幕阅读器对标记和 GeoJSON 的识别。

扩展功能

1. 动态标记添加

允许用户点击地图添加新标记:

import { useMapEvent } from 'react-leaflet';const MapEvents: React.FC<{ onAddMarker: (coords: [number, number]) => void }> = ({ onAddMarker }) => {useMapEvent('click', e => {onAddMarker([e.latlng.lat, e.latlng.lng]);});return null;
};// 在 CityMap 中添加
const [nextId, setNextId] = useState(4);
const handleAddMarker = (coords: [number, number]) => {setMarkers(prev => [...prev,{ id: nextId, name: `新标记 ${nextId}`, coords, description: '用户添加的标记' },]);setNextId(prev => prev + 1);if (mapRef.current) {mapRef.current.getContainer()?.setAttribute('aria-live', 'polite');const desc = document.getElementById('map-desc');if (desc) desc.textContent = `新标记添加在经纬度: ${coords[0].toFixed(4)}, ${coords[1].toFixed(4)}`;}
};// 在 MapContainer 中添加
<MapEvents onAddMarker={handleAddMarker} />

2. 响应式适配

使用 Tailwind CSS 确保地图在手机端自适应:

.leaflet-container {@apply h-[600px] sm:h-[700px] md:h-[800px] w-full max-w-4xl mx-auto;
}

3. 动态缩放聚焦

点击 GeoJSON 图层时,自动缩放地图:

onEachFeature={(feature, layer) => {layer.on({click: () => {mapRef.current?.fitBounds(layer.getBounds());},});
}

常见问题与解决方案

1. React-Leaflet DOM 冲突

问题:React-Leaflet 与 React 的虚拟 DOM 冲突,导致渲染错误。
解决方案

  • 使用 MapContainer 而非 L.map 直接操作 DOM。
  • 确保事件处理通过 eventHandlers 绑定。
  • 测试 React DevTools,检查组件状态。

2. 可访问性问题

问题:屏幕阅读器无法识别标记或 GeoJSON。
解决方案

  • 为 Marker 和 GeoJSON 添加 aria-labelaria-describedby
  • 使用 aria-live 通知动态更新。
  • 测试 NVDA 和 VoiceOver。

3. 性能瓶颈

问题:大数据量 GeoJSON 或标记渲染卡顿。
解决方案

  • 使用 React Query 缓存数据。
  • 启用 Canvas 渲染(L.canvas())。
  • 测试低端设备(Chrome DevTools 设备模拟器)。

4. 数据加载延迟

问题:异步数据加载导致地图闪烁。
解决方案

  • 显示加载状态(isLoading)。
  • 使用 React Query 的 placeholderData
  • 测试网络性能(Chrome DevTools)。

部署与优化

1. 本地开发

运行本地服务器:

npm run dev

2. 生产部署

使用 Vite 构建:

npm run build

部署到 Vercel:

  • 导入 GitHub 仓库。
  • 构建命令:npm run build
  • 输出目录:dist

3. 优化建议

  • 压缩资源:使用 Vite 压缩 JS 和 CSS。
  • CDN 加速:通过 unpkg 或 jsDelivr 加载 React-Leaflet 和 LeafletJS。
  • 缓存数据:React Query 自动缓存,减少重复请求。
  • 可访问性测试:使用 axe DevTools 检查 WCAG 合规性。

注意事项

  • React-Leaflet 版本:确保与 LeafletJS 1.9.4 兼容(推荐 React-Leaflet 4.0.0)。
  • 可访问性:严格遵循 WCAG 2.1,确保 ARIA 属性正确使用。
  • 性能测试:定期使用 React DevTools 和 Lighthouse 分析瓶颈。
  • 瓦片服务:OpenStreetMap 适合开发,生产环境可考虑 Mapbox。
  • 学习资源
    • React-Leaflet 文档:https://react-leaflet.js.org
    • LeafletJS 官方文档:https://leafletjs.com
    • React Query 文档:https://tanstack.com/query
    • WCAG 2.1 指南:https://www.w3.org/WAI/standards-guidelines/wcag/

总结与练习题

总结

本文通过交互式城市地图案例,展示了如何将 LeafletJS 集成到 React 18 中,利用 React-Leaflet 实现标记拖拽和 GeoJSON 数据渲染。结合 React Query 管理异步数据、Tailwind CSS 实现响应式布局,地图实现了高效、交互性强且可访问的功能。性能测试表明,Canvas 渲染和数据缓存显著提升了渲染效率,WCAG 2.1 合规性确保了包容性。本案例为开发者提供了现代地图开发的完整流程,适合进阶学习和实际项目应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91879.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前后端数据交互,关于表单数据传输问题

表单提交var formData new FormData(); // 添加每个事故ID作为单独的参数 accidentIds.forEach(id > formData.append(accidentIds, id)); formData.append(status, statusText); $.messager.confirm(确认, 确定要将事故记录标记为 statusText 吗&#xff1f;, function …

新书推介 | 吉林大学出版教材《汽车智能辅助驾驶系统技术》,国产仿真工具链GCKontrol-GCAir教学应用

近日&#xff0c;吉林大学出版了由高镇海教授、孙天骏副教授主编的新教材《汽车智能辅助驾驶系统技术》&#xff0c;本书系统地介绍了汽车智能辅助驾驶系统的发展需求、物理架构、功能算法、技术原理以及应用场景。在教材第17章《仿真测试》&#xff0c;应用国产化GCKontrol-GC…

从 0 到 1 玩转 XSS - haozi 靶场:环境搭建 + 全关卡漏洞解析

文章目录前言靶场地址0X00 直接注入0X01 闭合标签10X02 闭合标签20X03 绕过特殊符号10X04 绕过特殊符号20X05 绕过注释符0X06 绕过更多符号0X07 绕过更多符号20X08 绕过闭合符号0X09 绕过URL匹配0X0A 绕过URL过滤0X0B 绕过大写转换10X0C 绕过大写转换20X0D 绕过注释0X0E 古英语…

TF卡格式化

cmd 输入diskpart,在新打开的窗口输入list disk&#xff0c;然后select disk [磁盘号]&#xff0c;clean&#xff0c;回车变成未分区的。再选中磁盘&#xff0c;选中之后create partition [分区名] 回车&#xff0c;list partition&#xff0c;查看分区&#xff0c;输入active&…

Python爬虫实战:研究sqlparse库相关技术

1. 引言 1.1 研究背景与意义 在当今数据驱动的时代,SQL 作为关系型数据库的标准查询语言,被广泛应用于各种数据处理和分析场景。随着数据库应用的不断发展,SQL 代码的规模和复杂度也在不断增加,这给 SQL 代码的编写、维护和优化带来了挑战。 研究表明,低效的 SQL 查询是…

全球天气预报5天(经纬度版)免费API接口教程

本文全面介绍由接口盒子免费API提供的全球天气预报API&#xff0c;支持通过经纬度坐标获取任意地区未来5天的详细天气预报数据。 一、接口核心功能 ​全球覆盖​&#xff1a;支持全球任意经纬度坐标点的天气预报​高精度预报​&#xff1a;提供每3小时为间隔的精细化预报&…

5 基于STM32单片机的绝缘检测系统设计(STM32代码编写+手机APP设计+PCB设计+Proteus仿真)

系列文章目录 文章目录 系列文章目录前言1 1 资料获取与演示视频1.1 资料介绍1.2 资料获取1.3 演示视频 2 系统框架3 硬件3.1 主控制器3.2 显示屏3.3 WIFI模块3.4 DHT11温湿度传感器3.5 可调电位器 4 设计PCB4.1 安装下载立创EDA专业版4.2 画原理图4.3 摆放元器件&#xff0c;设…

CPP学习之list使用及模拟实现

一、list简介及用法 1. list简介 list是可以在常数范围内任意位置进行插入、删除、修改操作的有顺序性的容器&#xff0c;而且支持双向迭代&#xff0c;其底层是双链表结构&#xff0c;逻辑上连续但物理空间上不连续&#xff0c;只能通过指针来进行元素访问&#xff0c;无法使用…

Spring Boot 参数校验:@Valid 与 @Validated

在日常开发中&#xff0c;参数校验是保障接口健壮性与数据安全的第一道防线。Spring Boot 为我们提供了基于 JSR-303/JSR-380 的强大校验机制&#xff0c;通过注解与 AOP 实现了灵活且高效的数据校验方式。本篇博客将详细介绍 Spring Boot 中 Valid、Validated 注解的使用方法&…

linux看门狗重启定位思路总结

1&#xff0c;看门狗定位思路&#xff08;1&#xff09;是否是死锁导致查看日志查看是否有RCU install或者deadlock相关打印&#xff0c;如果有的话可以考虑使用lockdep死锁检测工具&#xff08;2&#xff09;中断风暴查看中断&#xff0c;抓中断打印&#xff0c;可以查看/proc…

基于单片机直流电机测速中文液晶显示设计

摘 要 在现在工业自动化高度发展的时期&#xff0c;几乎所有的工业设备都离不开旋转设备&#xff0c;形形色色的电机在不同领域发挥着很重要的作用。不同场合对电机控制要求是不同的&#xff0c;但大部分都会涉及到旋转设备的转速测量&#xff0c;从而利用转速来实施对旋转设备…

c# sqlsugar 主子表明细 查询

在使用 SqlSugar ORM 进行数据库操作时&#xff0c;特别是在处理主子表关系时&#xff0c;通常需要执行关联查询来获取主表和其子表的数据。SqlSugar 提供了强大的查询能力&#xff0c;支持多种方式的关联查询&#xff0c;包括左连接&#xff08;Left Join&#xff09;、内连接…

研华PCI-1285/1285E 系列------(一概述)

PCI-1285/1285E 系列是基于 DSP 的 SoftMotion PCI 总线控制器卡,专为各种电机自动 化和其它机器自动化的广泛应用设计。板卡配有高性能 DSP,其中包括 SoftMotion算法,能够实现运动轨迹和时间控制,以满足精确运动中的同步应用需求。 研华 SoftMotion 支持以下特性:龙门…

二代身份证识别技术的发展:从机器学习到深度学习

一、技术发展历程1. 传统机器学习时代&#xff08;2000-2012&#xff09;特征工程方法&#xff1a;主要依赖手工设计的特征&#xff08;HOG、SIFT、LBP等&#xff09;分类器技术&#xff1a;支持向量机(SVM)、随机森林、AdaBoost等OCR技术&#xff1a;基于模板匹配和连通区域分…

云服务器如何设置防火墙和安全组规则?

一、安全组&#xff08;Security Group&#xff09;设置安全组是云平台提供的虚拟防火墙&#xff0c;用于控制 入站&#xff08;Ingress&#xff09;和出站&#xff08;Egress&#xff09;流量。1. 基本安全组规则&#xff08;推荐&#xff09;协议端口源IP用途是否必需TCP22你…

排序【各种题型+对应LeetCode习题练习】

目录 常用排序 快速排序 LeetCode 912 排序数组 归并排序 LeetCode 912 排序数组 常用排序 名称排序方式时间复杂度是否稳定快速排序分治O(n log n)否归并排序分治O(n log n)是冒泡排序交换O(n)是插入排序插入O(n)是选择排序选择最值O(n)否C STL sort快排内省排序O(n log…

鸿蒙与web混合开发双向通信

鸿蒙与web混合开发双向通信用runJavaScript和registerJavaScriptProxy web entry/src/main/resources/rawfile/1.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&q…

unity Physics.RaycastNonAlloc

Physics.RaycastNonAlloc 是 Unity 中用于 3D 物理射线检测的高性能方法&#xff0c;它是 Physics.Raycast 的非分配版本。 方法签名 public static int RaycastNonAlloc(Ray ray, RaycastHit[] results, float maxDistance Mathf.Infinity, int layerMask DefaultRaycastLay…

数据库(five day finally)——物物而不物于物,念念而不念于念。(数据库到此结束!祝世间美好与各位不期而遇,善意常伴汝身!)

1.子查询&#xff08;1&#xff09;where 子查询①多行单列配合in和not in操作&#xff08;类似于数据范围查询&#xff09;例&#xff1a;显示工资与各个经理相同的雇员信息&#xff08;包含经理本身&#xff09;。select * from empwhere sal(select sal from emp where jobM…

【甲烷数据集】Sentinel-5P 卫星获取的全球甲烷数据集-TROPOMI L2 CH₄

目录 数据概述 传感器 & 卫星信息 监测目标:甲烷(CH₄) 数据产品内容 空间与时间覆盖 云筛选与协同观测 技术文档资源 数据下载 Python 代码绘制 CH4 数据 参考 数据概述 Sentinel-5 Precursor Level 2 Methane (TROPOMI L2 CH₄) 数据集是由欧洲哥白尼计划的 Sentinel…