当前位置: 首页 > news >正文

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>);
}

相关文章:

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

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

【Qt】常用的类与数据类型

目录 一、Qt常见基本数据类型 二、Qt 字符串类应用 2.1 操作字符串 2.2 查询字符串 三、QMap 类&QHash 类&QVector 类 3.1 QMap 类 3.2 QHash 类 3.3 QVector 类 四、QList 类&QLinkedList 类 4.1 QList 类 4.2 QLinkedList 类 4.3 STL 风格迭代器遍历…...

React实现B站评论Demo

该Demo涉及的技术点 useState函数&#xff08;数据驱动视图&#xff09;子组件的封装条件判断回调函数的封装 1、评论数据 {"list": [{"rpid": 3,"user": {"uid": "13258165","avatar": "http://toutiao.…...

从实列中学习linux shell12 通过Shell脚本来优化MySQL数据库性能,特别是慢SQL跟踪和索引优化

在Shell脚本中优化MySQL数据库性能&#xff0c;特别是慢SQL跟踪和索引优化 可以通过以下步骤实现。以下是一个结构化的解决方案&#xff0c;包含示例代码和详细说明&#xff1a; 1. 启用慢查询日志 目标&#xff1a;动态启用慢查询日志并配置参数&#xff0c;收集慢SQL数据。…...

ES6入门---第三单元 模块一:类、继承

补充&#xff1a; prototype 属性使您有能力向对象添加属性和方法。 object.prototype.namevalue <script>function Person(name, age){this.name name;this.age age;}/* Person.prototype.showName function(){return 名字为: ${this.name};};Person.prototype.showA…...

CSS 变量与原生动态主题实现

CSS 变量与原生动态主题实现 CSS 变量基础 CSS 变量&#xff08;自定义属性&#xff09;是 CSS 语言的一项强大功能&#xff0c;允许我们在样式表中定义和重用值。与 SCSS 或 LESS 等预处理器中的变量不同&#xff0c;CSS 变量在运行时计算&#xff0c;这意味着它们可以动态更…...

Ubuntu 安装 Docker

安装 Docker 1. 卸载旧版本&#xff08;如果有&#xff09; sudo apt-get remove docker docker-engine docker.io containerd runc 2. 更新 APT 包的索引 sudo apt-get update 3. 安装依赖包 sudo apt-get install -y \ca-certificates \curl \gnupg \lsb-release4. 添加…...

SpringMVC——第三章:获取请求数据

假设有这样一个请求&#xff1a;http://localhost:8080/springmvc/register?namezhangsan&password123&emailzhangsanpowernode.com 在SpringMVC中应该如何获取请求提交的数据呢&#xff1f; 在SpringMVC中又应该如何获取请求头信息呢&#xff1f; 在SpringMVC中又应…...

动静态库【Linux操作系统】

文章目录 动静态库制作静态库如何把第三方库安装在Linux系统中&#xff0c;如何使用第3方库方案一&#xff1a;为什么我们之前使用gcc/g编译C/C标准库的时候不用加选项-l xxx呢&#xff1f;方案二&#xff1a;方案三&#xff1a; 为什么不同平台的库不一样呢&#xff1f;动态库…...

Day 4:牛客周赛Round 91

好久没写了&#xff0c;问题还蛮多的。听说这次是苯环哥哥出题 F题 小苯的因子查询 思路 考虑求因子个数&#xff0c;用质因数分解&#xff1b;奇数因子只需要去掉质数为2的情况&#xff0c;用除法。 这里有个比较妙的细节是&#xff0c;提前处理出数字x的最小质因数&#xff0…...

drawDB:打造高效数据库设计流程

drawDB&#xff1a;打造高效数据库设计流程 drawDB 简介资源链接 核心功能详解1. 直观的实体关系图设计2. SQL 脚本生成3. SQL 导入功能4. 本地化存储与分享功能5. 自定义主题与外观 安装和使用教程本地开发环境搭建构建生产版本Docker 部署基本使用方法 应用场景和实际价值适用…...

【心海资源】子比主题新增注册与会员用户展示功能模块及实现方法

内容改写&#xff1a; 本次分享的是子比主题顶部展示注册用户与会员信息的功能模块及其实现方式。 你可以通过两种方式启用该功能&#xff1a; 直接在后台进入“外观 → 小工具”启用该展示模块&#xff0c;操作简便&#xff1b;也可将提供的代码覆盖至子比主题目录中&#…...

gitblit安装教程,搭建一个属于自己的Git版本仓库

本章教程,主要记录如何在Windows服务器上利用gitblit搭建GIT私有化仓库。 一、gitblit简介 官网地址:https://www.gitblit.com/ Gitblit 是一个开源的纯 Java 技术栈,用于管理、查看和服务Git仓库。 它主要设计为一款面向希望托管集中式仓库的小型工作组的工具。 二、基础环…...

2023年第十四届蓝桥杯省赛B组Java题解【简洁易懂】

2023年第十四届蓝桥杯省赛B组Java题解 题型概览与整体分析 题目编号题目名称题型难度核心知识点通过率&#xff08;预估&#xff09;A阶乘求和结果填空★☆☆模运算、数学规律95%B幸运数字结果填空★★☆进制转换、数位和计算80%C数组分割编程题★★☆组合数学、奇偶性分析65…...

Javase 基础加强 —— 01 异常

本系列为笔者学习Javase的课堂笔记&#xff0c;视频资源为B站黑马程序员出品的《黑马程序员JavaAI智能辅助编程全套视频教程&#xff0c;java零基础入门到大牛一套通关》&#xff0c;章节分布参考视频教程&#xff0c;为同样学习Javase系列课程的同学们提供参考。 01 课程安排…...

iview 表单验证问题 Select 已经选择 还是弹验证提示

问题&#xff1a;iview 的 Select 下拉框的时候&#xff0c;数据验证必填&#xff0c;明明选择了数据&#xff0c;却一直提示验证不能通过 html代码&#xff1a; <Form ref"FormData" :model"FormData" :rules"ruleValidate" :label-width&qu…...

OrCAD中离图连接器、端口及网络标签的作用范围与选择指南

一、OrCAD主要连接元素概述 在OrCAD Capture原理图设计环境中&#xff0c;有三种主要的网络连接元素&#xff1a;离图连接器(Off-Page Connector)、端口(Port)和网络标签(Net Alias)。理解它们的作用范围和使用场景对设计清晰、可维护的原理图至关重要。 PS&#xff1a; 电源和…...

dpm_sysfs_add

这段代码是 Linux 内核中**设备电源管理&#xff08;PM&#xff09;子系统**与 **sysfs 文件系统**交互的核心实现&#xff0c;主要功能是为设备创建电源管理相关的 sysfs 属性文件。以下从五个关键维度进行深度解析&#xff1a; --- ### 一、功能架构全景 mermaid graph TD …...

【AI论文】Phi-4-reasoning技术报告

摘要&#xff1a;我们引入了Phi-4-reasoning&#xff0c;这是一种拥有140亿参数的推理模型&#xff0c;在复杂的推理任务中表现出了强大的性能。 通过监督式微调Phi-4&#xff0c;在精心策划的“可教”提示集上进行训练&#xff0c;这些提示集是根据复杂性和多样性的适当水平选…...

Android ART运行时无缝替换Dalvik虚拟机的过程分析

目录 一,概述 二,dex文件优化 一,概述 Android 4.4发布了一个ART运行时&#xff0c;准备用来替换掉之前一直使用的Dalvik虚拟机&#xff0c;希望籍此解决饱受诟病的性能问题。老罗不打算分析ART的实现原理&#xff0c;只是很有兴趣知道ART是如何无缝替换掉原来的Dalvik虚拟机…...

node.js为什么产生?

从官网得知介绍如下 https://nodejs.org/zh-cn/learn/getting-started/introduction-to-nodejs Node.js是一个开源和跨平台的JavaScript运行时环境。 Node.js在浏览器之外运行V8 JavaScript引擎&#xff0c;这是Google Chrome的核心。这使得Node.js具有很高的性能。 Node.js应…...

智能工厂边缘计算:从数据采集到实时决策

智能工厂边缘计算:从数据采集到实时决策 引言 在智能制造场景中,传统云计算架构面临三大核心挑战:平均200ms的网络延迟无法满足实时控制需求,90%的工业数据未被有效利用,以及每月高达15TB的数据传输成本。边缘计算技术通过将计算能力下沉到数据源头,正在构建"端-边…...

个人健康中枢的多元化AI网络革新与精准健康路径探析

引言 随着数字化转型的深入推进,个人健康中枢作为集成化健康管理系统,正在从传统的单一功能向多元化的AI驱动方向快速发展。在这一背景下,新兴网络硬件技术,特别是DPU(数据处理单元)和全光网络的出现,为个人健康中枢的革新提供了前所未有的机遇。本研究将深入探讨这些技…...

前端面试宝典---性能优化

一、加载优化 1. 第三方模块放在CDN 例如 leaflet通过cdn引入&#xff0c;这样就不会占用打包体积了 2. prefetch 预加载 例如&#xff0c;之后马上有个场景需要一个图片&#xff0c;我们就可以通过link 的 prefetch 对资源进行预先加载 再例如&#xff0c;我们公司是无网络开…...

【Springboot进阶】springboot+mybatis+jsqlparser实现数据权限控制

文章目录 SpringBoot JSqlParser MyBatis 数据权限实现方案一、环境准备1. 添加依赖 二、用户上下文管理1. 用户上下文持有类 三、数据权限拦截器实现1. MyBatis拦截器核心类 四、Spring Security集成1. 用户信息注入 五、配置项示例application.yml 六、使用示例1. 业务查询…...

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】2.3 窗口函数与高级聚合(ROW_NUMBER()/RANK()/SUM() OVER())

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL窗口函数与高级聚合:从排序到动态分析的全场景应用1. 窗口函数核心概念解析1.1 窗口函数语法结构1.2 核心组成要素2. 排名窗口函数深度解析2.1 ROW_NUMBER():唯一顺序排名示例演示2.2 `RANK…...

python全自动爬取m3u8网页视频(各类网站都通用)

当前人工智能&#xff0c;大语言模型的火热&#xff0c;使得python这门编程语言的使用越来越广泛。最近也开始学习了python&#xff0c;发现它在自动化方面的确有得天独厚的优势。python的简单易用&#xff0c;丰富的开源库&#xff0c;完善的生态&#xff0c;使得它有可能成为…...

C++负载均衡远程调用学习之上报功能与存储线程池

目录 1. Lars-reportV0.1 report模块介绍 2.Lars-reporterV0.1 reporter项目目录构建 3.Lars-ReporterV0.1 数据表和proto协议环境搭建 4.Lars-ReporterV0.1上报请求业务处理 5.Lars-ReporterV0.1上报请求模块的测试 6.Lars-ReporterV0.2开辟存储线程池-网络存储分离 1. L…...

今天python练习题

目录 一、每日一言 二、练习题 三、效果展示 四、下次题目 五、总结 一、每日一言 不要害怕失败&#xff0c;失败可能成为我们前进的动力&#xff01; 二、练习题 有列表lst [[1,2,3],[4,5,6],[7,8,9]],取出其中的元素1/5/9组成新的列表 # 有列表lst [[1,2,3],[4,5,6],[…...

【leetcode100】最长递增子序列

1、题目描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 …...

R绘图|3分钟复现瑞士“苏黎世大学”Nature全球地图——基于R包ggplot2+sf等

一、引言 本文我们复现苏黎世大学团队Franois Keck等在Nature最新文章“The global human impact on biodiversity”中的全球地图。 之前的图纸是在平面坐标系里面进行绘制&#xff0c;本次我们在罗宾逊投影中进行绘制。整体代码逻辑非常简单&#xff0c;就是采样点坐标系的转换…...

百度系列产品学习

1.react-bmapgl封装逻辑 Map 分析react-bmapgl库中Map组件的封装流程&#xff0c;并以mermaid图展示。首先分析Map组件的核心实现&#xff0c;包括生命周期方法和子组件渲染逻辑。然后研究WrapperHOC和Component基类的封装模式&#xff0c;理解事件绑定和属性处理的通用逻辑。…...

高等数学第三章---微分中值定理与导数的应用(3.4~3.5)

3.4 函数的单调性与曲线的凹凸性 一、函数的单调性 1. 函数单调性定义回顾 设函数 f ( x ) f(x) f(x) 的定义域为 D D D&#xff0c;区间 I ⊆ D I \subseteq D I⊆D。 如果对任意 x 1 , x 2 ∈ I x_1, x_2 \in I x1​,x2​∈I&#xff0c;当 x 1 < x 2 x_1 < x…...

idea结合CopilotChat进行样式调整实践

一、前言&#xff1a; 本文主要分享在前端开发中借助AI能力调整样式&#xff0c;提高开发效率 对应视频【idea结合CopilotChat进行样式调整实践-哔哩哔哩】 二、实践&#xff1a; 2-1、现状确认&#xff1a; 表格上方新增了button、swtich、select组件&#xff0c;需要调整…...

668SJBH报刊发行系统

1 前言 随着我国信息产业的迅猛发展&#xff0c;手工管理方式已不适应社务管理的要求&#xff0c;报社的日常管理正面临着信息化的挑战&#xff0c;采用计算机管理以提高服务质量和管理水平势在必行。发行管理是社务管理的一个重要组成部分&#xff0c;是报社和客户联系的纽带…...

格式化字符串漏洞

原理 在c中&#xff0c;printf函数在打印输出变量时通常不是直接输出&#xff0c;而是用一个占位符如%s printf("the number is %d\n",a);//通常用 printf(a);//而不是直接输出 虽然直接输出也没有太大的问题&#xff0c;但如果用格式化输出&#xff0c;没有给后面…...

如何查看电脑IP地址和归属地:全面指南

在数字化时代&#xff0c;了解自己电脑的IP地址和归属地信息变得越来越重要。无论是进行网络故障排查、远程办公设置&#xff0c;还是出于网络安全考虑&#xff0c;掌握这些基本信息都很有必要。本文将详细介绍如何查看电脑的公网IP、内网IP以及归属地信息&#xff0c;并提供常…...

深入解析 MQTT 协议:物联网通信的基石

在当今物联网蓬勃发展的时代&#xff0c;设备之间高效、可靠的通信变得至关重要。MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;协议&#xff0c;作为一种轻量级的消息传输协议&#xff0c;正逐渐成为物联网通信的基石&#xff0c;广泛应用于各种场景中。 …...

48变现干货:分销裂变方式提高销量

产品运营活动中,我们可以根据对产品属性和特性,进行选择特定的方法,分销便是一种低成本各方获利的行为之一,但并不一定100%适用所有产品。 分销及裂变的概念 “分销”是指通过用户、达人、KOL等非官方渠道,参与产品的推广与销售,并获得相应收益的机制。它是一种以奖励为…...

AI入门:Prompt提示词写法

提示词&#xff08;Prompt&#xff09;是人与AI沟通的桥梁&#xff0c;它不是冰冷的代码指令&#xff0c;而是一场充满智慧与温度的对话。掌握精妙的提示词撰写技巧&#xff0c;能让AI更精准地理解需求&#xff0c;高效输出理想结果。其核心就在于——将AI视作身边真实的朋友、…...

MySQL复合查询全解析:从基础到多表关联与高级技巧

前言&#xff1a; 本文主要讲解了在MySQL中的复合查询&#xff0c;下面是关于本文章所需要数据的建表语句 创建表的语句&#xff1a; DROP database IF EXISTS scott; CREATE database IF NOT EXISTS scott DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;USE scott;D…...

移动 Trae 目录到 E 盘 - 解决 C 盘空间不足问题

移动 Trae 目录到 E 盘 - 解决 C 盘空间不足问题 1️⃣ 准备工作2️⃣ 移动原始文件夹3️⃣ 创建符号链接4️⃣ 清理原始文件夹5️⃣ 验证操作📝 注意事项🔄 常见问题排查1️⃣ 准备工作 关闭 Trae 程序:确保所有 Trae 相关进程已完全退出(包括后台服务)。创建目标文件夹…...

【AI论文】COMPACT:从原子级到复杂级的组合式视觉能力调优

摘要&#xff1a;多模态大语言模型&#xff08;MLLM&#xff09;擅长简单的视觉语言任务&#xff0c;但在面对需要多种能力的复杂任务时却很吃力&#xff0c;例如同时识别物体、计算数量和理解它们的空间关系。 这可能部分是由于视觉指令调整&#xff08;VIT&#xff09;这一ML…...

【leetcode】队列 + 宽搜,树形结构层序遍历的基础与变化

前言 &#x1f31f;&#x1f31f;本期讲解关于力扣的几篇题解的详细介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…...

Spring AI聊天模型API:轻松构建智能聊天交互

Spring AI聊天模型API&#xff1a;轻松构建智能聊天交互 前言 在当今数字化时代&#xff0c;智能聊天功能已成为众多应用程序提升用户体验、增强交互性的关键要素。Spring AI的聊天模型API为开发者提供了一条便捷通道&#xff0c;能够将强大的AI驱动的聊天完成功能无缝集成到…...

力扣-链表-2 两数相加

思路 两个指针同时遍历&#xff0c;维护一个进位值&#xff0c;同时还要维护第一个链表的前序&#xff0c;如果第二个链表比第一个长的时候&#xff0c;利用这个前序指针把第二个链表多余的内容&#xff0c;添加到第一个链表的末尾 代码 class Solution {public ListNode ad…...

leetcode 59. 螺旋矩阵 II

题目描述 代码&#xff1a; class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n,vector<int>(n,0));int num 1;int len n;int start 0;while(len > 0){int row start;int column start;if…...

【操作系统】深入理解内存管理:从虚拟内存到OOM Killer

引言 在现代计算机系统中&#xff0c;内存管理是操作系统最核心的功能之一。本文将围绕内存管理的几个关键概念展开讨论&#xff0c;包括虚拟内存机制、内存分配原理、OOM Killer的工作机制以及不同系统架构下的内存限制。 虚拟内存&#xff1a;突破物理限制的关键技术 虚拟…...

《政治最后的日子》章节

政治与中世纪教会的类比性衰落 作者提出现代民族国家正重复中世纪教会的衰落轨迹&#xff1a; 两者均曾作为社会组织核心存在约5个世纪 晚期都成为生产力阻碍&#xff08;中世纪教会税收负担/现代国家官僚低效&#xff09; 末期均出现管理者普遍腐败与公众蔑视&#xff08;…...

Rust Trait 学习

概述 特征&#xff08;trait&#xff09;是rust中的概念&#xff0c;类似于其他语言中的接口&#xff08;interface&#xff09;。特征定义了一个可以被共享的行为&#xff0c;只要实现了特征&#xff0c;你就能使用该行为。 如果不同的类型具有相同的行为&#xff0c;那么我们…...