React--》掌握react构建拖拽交互的技巧

在这篇文章中将深入探讨如何使用react-dnd,从基础的拖拽操作到更复杂的自定义功能带你一步步走向实现流畅、可控且用户友好的拖拽体验,无论你是刚接触拖拽功能的初学者还是想要精细化拖拽交互的经验开发者,都能从中找到适合自己的灵感和解决方案。

目录

react-dnd操作

拖拽排序操作

拖拽移动操作

react-beautiful-dnd操作

dnd-kit操作

react-dnd操作

        react-dnd:一个用于在react应用中实现拖拽和放置功能的库,它为开发者提供了一套灵活且可扩展的工具使得在react中处理拖拽交互变得简单且高效,通过react-dnd开发者可以轻松地创建拖拽组件、设置拖拽目标以及处理拖拽过程中各个阶段的事件(如开始拖拽、拖拽过程中、放置等),它不仅支持基础的拖拽功能还允许开发者自定义拖拽行为、指定可放置区域、调整拖拽元素的样式等,详情请阅读官方文档:地址 ,当然也可以去看看源码:地址 进行学习,接下来我们终端执行如下命令进行安装react-dnd,以下是使用拖拽的具体步骤:

npm install react-dnd react-dnd-html5-backend

包裹容器:接下来我们开始实现拖拽操作,react-dnd提供一个上下文提供者DndProvider,它用于在应用中启用拖拽功能并且是实现拖拽交互的基础,所有需要拖拽行为的组件都必须包裹在DndProvider中

HTML5Backend是react-dnd的一个后端实现,用于处理浏览器中的拖拽操作,通过引入react-dnd可以在浏览器中启用标准的拖拽行为,代码如下所示:

import Drag from './components/drag'
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';const App = () => {return (<DndProvider backend={ HTML5Backend }><Drag></Drag></DndProvider>)
}export default App

拖拽源:接下来我们开始设置拖拽源操作,react-dnd提供了useDrag用来提供对拖拽元素的一些操作,具体的代码逻辑如下所示:

import { useDrag } from "react-dnd";
import "./index.less";const Draggable = () => {/*** 参数1:返回值是一个对象,主要放一些拖拽物的状态* 参数2:ref实例,只要将它注入到DOM中该DOM就会变成一个可拖拽的DOM*/const [{ isDragging }, dragRef]: any = useDrag(() => ({type: "box", // 拖拽的类型,要和接收者那边的类型对应上item: { id: "1" }, // 拖拽的数据,要和接收者那边的数据对应上collect: (monitor) => ({ // 拖拽过程中的一些状态,要和接收者那边的数据对应上isDragging: monitor.isDragging(),}),}));return <div ref={dragRef} className="drag"></div>;
};export default Draggable;

通过如上代码,调整一下css样式之后,我们就可以对我们定义的div盒子进行拖拽操作了,如下:

如果想隐藏在拖拽过程中原本为啥的元素,可以通过参数1中的对象来确定是否在拖拽中,如果拖拽的话直接隐藏原本元素就好了,代码如下:

import { useDrag } from "react-dnd";
import "./index.less";const Draggable = () => {/*** 参数1:返回值是一个对象,主要放一些拖拽物的状态* 参数2:ref实例,只要将它注入到DOM中该DOM就会变成一个可拖拽的DOM*/const [{ isDragging }, dragRef]: any = useDrag(() => ({type: "box", // 拖拽的类型,要和接收者那边的类型对应上item: { id: "1" }, // 拖拽的数据,要和接收者那边的数据对应上collect: (monitor) => ({ // 拖拽过程中的一些状态,要和接收者那边的数据对应上isDragging: monitor.isDragging(),}),}));if (isDragging) {return <div ref={dragRef}></div>;}return <div ref={dragRef} className="drag"></div>;
};export default Draggable;

当然我们也可以通过props传参的方式来实现不同拖拽的id的拖拽源,如下所示:

拖拽区域:接下来我们开始设置拖拽区域操作,react-dnd提供了useDrop用来提供对拖拽区域的一些操作,具体的代码逻辑如下所示:

import { useDrop } from "react-dnd";
import "./index.less";const Droppable = () => {const [{ isOver }, drop]: any = useDrop(() => ({accept: 'box', // 只接受box类型的数据collect: (monitor) => ({ // 收集器,用来获取拖拽过程中的一些信息isOver: monitor.isOver() }),drop: (item) => { // 放置事件处理函数console.log(item)}}))return <div ref={drop} className="drop"></div>;
};export default Droppable;

然后接下面我们定义几个拖拽源,然后将拖拽元素拖拽到拖拽区域里面,可以执行放置时间的处理函数从而打印一下对应的数据,如下所示:

drop这个回调事件可以写的很复杂这里我们可以将其抽离出去通过props来实现调用,useDrop支持第二个参数[state]作为依赖项,当你通过[state]将状态传入useDrop,你实际上是在告诉react当state发生变化时重新执行useDrop钩子,useDrop就能根据最新的state来决定目标区域的行为或者重新计算是否可以接受拖拽等,如下所示:

import { useDrop } from "react-dnd";
import "./index.less";const Droppable = ({ handleDrop, state, text, children }: any) => {const [{ isOver }, drop]: any = useDrop(() => ({accept: 'box', // 只接受box类型的数据collect: (monitor) => ({ // 收集器,用来获取拖拽过程中的一些信息isOver: monitor.isOver() }),drop: (item) => handleDrop(item) // 放置事件处理函数}), [state])return <div ref={drop} className="drop">{text}{children}</div>;
};export default Droppable;

拖拽排序操作

        拖拽排序:说白了就是改变原数据的位置顺序,这里我们使用了immutability-helper用于简化js中不可变数据操作的工具包,它提供一些简单API来更新嵌套的对象或数组而不会直接修改原数据,这样可以避免直接变更数据确保数据的不可变性,终端执行如下命令安装:

npm install immutability-helper

immutability-helper通常用于React中尤其是更新状态时,帮助避免直接改变state的问题,比如更新嵌套对象或者数组的某个值时immutability-helper会返回一个新的对象而不是修改原对象例如使用它更新数组中的元素:

import update from 'immutability-helper';const state = [1, 2, 3];
const newState = update(state, { 1: { $set: 4 } });console.log(newState); // [1, 4, 3]

接下来我们在拖拽排序中使用,其中useCallback确保了moveCard和 renderCard函数不会在每次组件渲染时被重新创建,这样避免了不必要的重新渲染和性能开销。如下所示:

import update from 'immutability-helper'
import { useCallback, useState } from 'react'
import { Card } from './Card'const Index = () => {const [cards, setCards] = useState([{ id: 1, text: 'Write a cool JS library' },{ id: 2, text: 'Make it generic enough' },{ id: 3, text: 'Write README' },{ id: 4, text: 'Create some examples' },{ id: 5, text: 'Spam in Twitter and IRC to promote it (note that this element is taller than the others)' },{ id: 6, text: '???' },{ id: 7, text: 'PROFIT' },])const moveCard = useCallback((dragIndex: number, hoverIndex: number) => {setCards((prevCards: any) => update(prevCards, {$splice: [[dragIndex, 1],[hoverIndex, 0, prevCards[dragIndex]],],}))}, [])const renderCard = useCallback((card: any, index: number) => {return (<Card type='card' key={card.id} index={index} id={card.id} text={card.text} moveCard={moveCard} />)}, [])return (<><div style={{ width: '400px' }}>{cards.map((card, i) => renderCard(card, i))}</div></>)
}export default Index

然后接下来我们将拖拽源和放置源写在同一个div区域内,这样标签内容就既可以拖拽又可以放置,具体代码如下所示,这里我们通过在div元素设置data-handler-id来唯一地标识该div元素,方便对其进行操作:

import { useRef } from 'react'
import { useDrag, useDrop } from 'react-dnd'const style = {border: '1px dashed gray',padding: '0.5rem 1rem',marginBottom: '.5rem',backgroundColor: 'white',cursor: 'move',
}export const Card = ({ id, text, index, moveCard, type }: any) => {const ref = useRef<HTMLDivElement>(null)const [{ handlerId }, drop] = useDrop({accept: type,collect: (monitor) => ({ // 收集器,用来获取拖拽过程中的一些信息handlerId: monitor.getHandlerId(), // 设置拖拽源的唯一标识,用来区分不同的拖拽源}),hover(item: any, monitor) {if (!ref.current) returnconst dragIndex = item.index // 拖拽元素的索引位置const hoverIndex = index // 鼠标悬停元素的索引位置if (dragIndex === hoverIndex) returnconst hoverBoundingRect = ref.current?.getBoundingClientRect() // 获取鼠标悬停元素的边界信息const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2 // 鼠标悬停元素的中点位置const clientOffset: any = monitor.getClientOffset() // 获取鼠标在页面中的位置信息const hoverClientY = clientOffset.y - hoverBoundingRect.topif (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) return // 如果拖拽元素在鼠标悬停元素的上方,并且鼠标位置在元素的中点下方,则不执行移动操作if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) return // 如果拖拽元素在鼠标悬停元素的下方,并且鼠标位置在元素的中点上方,则不执行移动操作moveCard(dragIndex, hoverIndex) // 调用moveCard函数,实现拖拽排序效果item.index = hoverIndex // 更新拖拽元素的索引位置},})const [{ isDragging }, drag] = useDrag({type,item: () => ({ id, index }),collect: (monitor: any) => ({isDragging: monitor.isDragging(),}),})const opacity = isDragging ? 0 : 1drag(drop(ref))return (<div ref={ref} style={{ ...style, opacity }} data-handler-id={handlerId}>{text}</div>)
}

最终呈现的效果如下所示:

拖拽移动操作

        拖拽移动:说白了就是改变原数据的left和top值,借助依赖项的变化来控制拖拽源不断改变其位置信息,如下我们定义一个拖拽源并且设置其依赖项的内容,如下所示:

import { useDrag } from 'react-dnd'const style: any = {position: 'absolute',border: '1px dashed gray',backgroundColor: 'white',width: '50px',height: '50px',cursor: 'move',
}
export const Box = ({ id, left, top, children, type }: any) => {const [{ isDragging }, drag]: any = useDrag(() => ({type,item: { id, left, top },collect: (monitor) => ({isDragging: monitor.isDragging(),}),}), [id, left, top])if (isDragging) return <div ref={drag} />return (<div ref={drag} style={{ ...style, left, top }}>{children}</div>)
}

然后我们通过如下代码来设置其规定只能在范围内进行移动,超出范围自动回到原本位置:

import update from 'immutability-helper'
import { useCallback, useState } from 'react'
import { useDrop } from 'react-dnd'
import { Box } from './Box'const styles: any = {width: 300,height: 300,border: '1px solid black',position: 'relative',
}const Index = () => {const [boxes, setBoxes] = useState<any>({a: { top: 20, left: 80, title: 'box1' },b: { top: 180, left: 20, title: 'box2' },})const moveBox = useCallback((id: string, left: number, top: number) => {setBoxes(update(boxes, {[id]: { $merge: { left, top } },}),)}, [boxes, setBoxes])const [, drop]: any = useDrop(() => ({accept: 'box',drop(item: any, monitor) { // 拖拽结束时触发的事件处理函数const delta: any = monitor.getDifferenceFromInitialOffset() // 获取鼠标移动的距离let left = Math.round(item.left + delta.x) // 计算新的left值let top = Math.round(item.top + delta.y) // 计算新的top值// 最小和最大边界限制left = Math.max(1, Math.min(left, 250));top = Math.max(1, Math.min(top, 250));moveBox(item.id, left, top) // 更新box的位置return undefined // 返回undefined,表示拖拽结束},}), [moveBox])return (<div style={{ display: 'flex', margin: '100px', gap: '30px' }}><div ref={drop} style={styles}>{Object.keys(boxes).map((key) => {const { left, top, title } = boxes[key]return (<Box key={key} id={key} left={left} top={top} type='box'>{title}</Box>)})}</div><div>box1: x坐标:{ boxes.a.left } - y坐标:{ boxes.a.top }<br/>box2: x坐标:{ boxes.b.left } - y坐标:{ boxes.b.top }</div></div>)
}export default Index

react-beautiful-dnd操作

        react-beautiful-dnd:是一个用于react的拖放(drag-and-drop)库,旨在帮助开发者在react应用中实现漂亮且易于使用的拖放交互,它提供了一个高效流畅且可访问的拖放体验,常用于实现类似列表排序卡片拖动等功能,终端执行如下命令安装:

npm install react-beautiful-dnd --save

它和react-dnd的区别主要在于其专注于排序方面的内容,优势如下,缺点就是React-beautiful-dnd 不支持React 高版本和严格模式,并且也是好几年没有维护了,大家需要根据自身情况选择是否去使用

1)拖放排序:支持列表项(如任务卡、文件等)的排序,可以拖动列表项改变其顺序。

2)跨列拖放:可以在多个列或容器之间拖动元素。

3)响应式:它的设计考虑了响应式和可访问性,使得即使是在移动设备上或使用键盘的用户也能够顺利使用拖放功能。

4)流畅动画:提供平滑的动画效果,使拖放过程更自然和易于理解。

5)高效:优化了性能,能够在大量元素的情况下依然流畅运行。

我们可以通过访问 链接 来查看其具体的实现案例操作,可以看到拖拽非常的丝滑,右侧菜单还提供了各种场景下的案例操作:

接下来我们就写一个简单的示例进行演示一下,代码如下所示:

import { useState, useCallback } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';// 设置数组的初始元素
const getItems = (count: any) =>Array.from({ length: count }, (_: any, k) => k).map(k => ({ id: `item-${k}`, content: `item ${k}`}));// 重新排序数组元素
const reorder = (list: any, startIndex: any, endIndex: any) => {const result = Array.from(list);const [removed] = result.splice(startIndex, 1);result.splice(endIndex, 0, removed);return result;
};
const grid = 8;
// 获取拖拽元素的样式
const getItemStyle = (isDragging: any, draggableStyle: any) => ({userSelect: 'none',padding: grid * 2,margin: `0 ${grid}px 0 0`,background: isDragging ? 'lightgreen' : 'grey',...draggableStyle,
});
// 获取列表的样式
const getListStyle = (isDraggingOver: any) => ({background: isDraggingOver ? 'lightblue' : 'lightgrey',display: 'flex',padding: grid,overflow: 'auto',
});const App = () => {const [items, setItems] = useState(getItems(6));const onDragEnd = useCallback((result: any) => {// 是否拖拽到了其他位置if (!result.destination) return;const reorderedItems: any = reorder(items,result.source.index,result.destination.index);setItems(reorderedItems);}, [items]);return (<DragDropContext onDragEnd={onDragEnd}><Droppable droppableId="droppable" direction="horizontal">{(provided: any, snapshot: any) => (<div ref={provided.innerRef} style={getListStyle(snapshot.isDraggingOver)} {...provided.droppableProps}>{items.map((item, index) => (<Draggable key={item.id} draggableId={item.id} index={index}>{(provided: any, snapshot: any) => (<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}style={getItemStyle( snapshot.isDragging, provided.draggableProps.style)}>{item.content}</div>)}</Draggable>))}{provided.placeholder}</div>)}</Droppable></DragDropContext>);
};export default App;

dnd-kit操作

        dnd-kit: 是一个用于实现拖放(drag-and-drop)交互的react库,它提供了一组高效灵活的API使开发者能够轻松构建具有拖放功能的应用,通过在浏览器中直接操作DOM元素并处理拖动放置以及元素重排的过程,使得用户能够在界面中拖动元素动态地改变其位置或顺序,终端执行如下命令安装:

npm install @dnd-kit/core

其主要优势如下所示:

1)简化拖放功能:封装了拖放的核心逻辑开发者无需从头开始编写复杂的拖放机制

2)高度自定义:提供了丰富的API开发者可以自定义拖动行为、动画效果、边界限制、拖动过程中元素的样式等

3)支持触摸屏和桌面设备:同时支持鼠标和触摸事件,适应不同设备。

4)性能优化:设计注重性能,通过高效的状态管理和渲染机制保证即使在复杂场景下也能流畅运行。

我们可以通过访问 链接 来查看其具体的实现案例操作,可以看到拖拽非常的丝滑,右侧菜单还提供了各种场景下的案例操作:

接下来我们就写一个简单的示例进行演示一下,代码如下所示:

import { useState } from 'react'
import { DndContext, useDroppable, useDraggable } from "@dnd-kit/core";// 设置放置和拖拽组件
const Droppable = (props: any) => {const {isOver, setNodeRef} = useDroppable({ id: props.id });return (<div ref={setNodeRef}>{props.children}</div>);
}
const Draggable = (props: any) => {const {attributes, listeners, setNodeRef, transform} = useDraggable({ id: props.id });const style = transform ? {transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,} : undefined;return (<div ref={setNodeRef} style={style} {...listeners} {...attributes}>{props.children}</div>);
}
export default function Index() {const containers = ['A', 'B', 'C','D','E'];const [parent, setParent] = useState(null);const draggableMarkup = (<Draggable id="draggable"><div style={{width:100,height:100,background:'pink',cursor:'move'}}>可拖拽组件</div></Draggable>);const handleDragEnd=(event: any)=> {const {over} = event;setParent(over ? over.id : null);}return (<DndContext onDragEnd={handleDragEnd}><div style={{display:'flex',justifyContent: 'space-between',paddingTop:50}}>{containers.map((id) => (<Droppable key={id} id={id}><div style={{width:200,height:200,border:'1px solid #000'}}>{parent === id ? draggableMarkup : '放置源'}</div></Droppable>))}</div>{parent === null ? draggableMarkup : null}</DndContext>);
}

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

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

相关文章

数据结构与算法:回溯

回溯 先给出一些leetcode算法题&#xff0c;以后遇见了相关题目再往上增加 主要参考代码随想录 2.1、组合问题 关于去重&#xff1a;两种写法的性能分析 需要注意的是&#xff1a;使用set去重的版本相对于used数组的版本效率都要低很多&#xff0c;大家在leetcode上提交&#x…

iview 分页改变每页条数时请求两次问题

问题 在iview page分页的时候&#xff0c;修改每页条数时&#xff0c;会发出两次请求。 iview 版本是4.0.0 原因 iview 的分页在调用on-page-size-change之前会调用on-Change。默认会先调用on-Change回到第一页&#xff0c;再调用on-page-size-change改变分页显示数量 此时就会…

一周学会Pandas2 Python数据处理与分析-Pandas2复杂数据查询操作

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们学了.loc[]等几个简单的数据筛选操作&#xff0c;但实际业务需求往 往需要按照一定的条件甚至复杂的组合条件…

【Vue bug】:deep()失效

vue 组件中使用了 element-plus 组件 <template><el-dialog:model-value"visible":title"title":width"width px":before-close"onClose"><div class"container" :style"{height:height px}"&g…

Trae 安装第三方插件支持本地部署的大语言模型

Trae 安装第三方插件支持本地部署的大语言模型 0. 引言1. 安装插件 0. 引言 字节发布的 Trae IDE 一直不支持本地部署的的大语言模型。 Qwen3 刚刚发布&#xff0c;想在 Trae 中使用本地部署的 Qwen3&#xff0c;我们可以在 Trae 中安装其他插件。 1. 安装插件 我们可以安装…

JavaScript 中的 Proxy 与 Reflect 教程

目录 get 和 set 捕获器详解 为什么要用 Reflect? 使用语法间接调用内部方法 使用 Reflect 直接调用内部方法 对比总结: Reflect API 及其与 Proxy 的配合 Proxy 的典型应用场景 Proxy 是 ES6 引入的一种元编程特性。它允许创建一个代理对象来包装目标对象,并拦截对目标…

基于STM32的心电图监测系统设计

摘要 本论文旨在设计一种基于 STM32 微控制器的心电图监测系统&#xff0c;通过对人体心电信号的采集、处理和分析&#xff0c;实现对心电图的实时监测与显示。系统采用高精度的心电信号采集模块&#xff0c;结合 STM32 强大的数据处理能力&#xff0c;能够有效去除噪声干扰&a…

C语言----操作符详解(万字详解)

目录 1. 操作符的分类 2. 二进制和进制转换 3. 原码 反码 补码 4. 移位操作符 4.1 左移操作符 >> 4.2 右移操作符 >> 5. 位操作符 5.1 按位与 & 5.2 按位或 | 5.3 按位异或 ^ 5.4 按位取反 ~ 练习 整数存储在内存中二进制中1的个数 练习 二进制位…

【进阶】C# 委托(Delegate)知识点总结归纳

1. 委托的基本概念 定义&#xff1a;委托是一种类型安全的函数指针&#xff0c;用于封装方法&#xff08;静态方法或实例方法&#xff09;。 核心作用&#xff1a;允许将方法作为参数传递&#xff0c;实现回调机制和事件处理。 类型安全&#xff1a;委托在编译时会检查方法签…

WebRTC 服务器之Janus视频会议插件信令交互

1.基础知识回顾 WebRTC 服务器之Janus概述和环境搭建-CSDN博客 WebRTC 服务器之Janus架构分析-CSDN博客 2.插件使用流程 我们要使⽤janus的功能时&#xff0c;通常要执⾏以下操作&#xff1a; 1. 在你的⽹⻚引入 Janus.js 库&#xff0c;即是包含janus.js&#xff1b; <…

Go语言中的无锁数据结构与并发效率优化

1. 引言 在高并发系统开发中&#xff0c;性能瓶颈往往出现在并发控制上。作为一个有着10年Go开发经验的后端工程师&#xff0c;我见证了无数因锁竞争导致的性能问题&#xff0c;也亲历了无锁编程为系统带来的巨大提升。 传统的锁机制就像是十字路口的红绿灯——虽然能确保安全…

STM32部分:2、环境搭建

飞书文档https://x509p6c8to.feishu.cn/wiki/DQsBw76bCiWaO4kS8TXcWDs0nAh Keil MDK用于编写代码&#xff0c;编译代码芯片支持包&#xff0c;用于支持某类芯片编程支持STM32CubeMX用于自动生成工程&#xff0c;减少手动重复工作 STM32F1系列芯片支持包 软件下载 直接下载&am…

U3D工程师简历模板

模板信息 简历范文名称&#xff1a;U3D工程师简历模板&#xff0c;所属行业&#xff1a;其他 | 职位&#xff0c;模板编号&#xff1a;B29EPQ 专业的个人简历模板&#xff0c;逻辑清晰&#xff0c;排版简洁美观&#xff0c;让你的个人简历显得更专业&#xff0c;找到好工作。…

Java设计模式: 实战案例解析

Java设计模式: 实战案例解析 在软件开发中&#xff0c;设计模式是一种用来解决特定问题的可复用解决方案。它们是经过实践验证的最佳实践&#xff0c;能够帮助开发人员设计出高质量、易于维护的代码。本文将介绍一些常见的Java设计模式&#xff0c;并通过实战案例解析它们在实际…

Vue3源码学习5-不使用 `const enum` 的原因

文章目录 前言✅ 什么是 const enum❌ 为什么 Vue 3 不使用 const enum1. &#x1f4e6; **影响构建工具兼容性**2. &#x1f501; **难以做模块间 tree-shaking**3. &#x1f9ea; **调试困难**4. &#x1f4e6; **Vue 是库&#xff0c;不掌控用户配置** ✅ 官方推荐做法&…

C++学习:六个月从基础到就业——C++11/14:lambda表达式

C学习&#xff1a;六个月从基础到就业——C11/14&#xff1a;lambda表达式 本文是我C学习之旅系列的第四十篇技术文章&#xff0c;也是第三阶段"现代C特性"的第二篇&#xff0c;主要介绍C11/14中引入的lambda表达式。查看完整系列目录了解更多内容。 引言 Lambda表达…

AIDC智算中心建设:计算力核心技术解析

目录 一、智算中心发展概览 二、计算力核心技术解析 一、智算中心发展概览 智算中心是人工智能发展的关键基础设施&#xff0c;基于人工智能计算架构&#xff0c;提供人工智能应用所需算力服务、数据服务和算法服务的算力基础设施&#xff0c;融合高性能计算设备、高速网络以…

IoTDB时序数据库V2.0.2大版本更新的一些梳理

一些小知识&#xff1a; 关于事务&#xff1a;时序数据库是没有事务的&#xff0c;它和关系数据库的应用场景不同&#xff0c;通常情况下不需要多点同时操作同一条数据&#xff0c;而且要保证极高的吐出量&#xff0c;事务太消耗资源&#xff0c;并且时序数据库提供了覆写的功能…

CSS定位详解

在前端开发中&#xff0c;CSS 定位&#xff08;positioning&#xff09;是一个核心概念&#xff0c;它决定了元素在页面上的位置和布局方式。无论是构建复杂的交互界面&#xff0c;还是实现简单的页面排版&#xff0c;CSS 定位都是不可或缺的工具。本文将全面介绍 CSS 中的五种…

React 语法扩展

useReducer钩子函数 不同action类型返回不同处理行为 useState()函数返回解构为两个值 state当前状态 dispatch修改状态函数 dispatch()函数参数为一个actuon对象 如 &#xff1a; 样例&#xff1a; import { useReducer } from react; import ./App.css;// 定义一个Reduce…