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

React 18 选择 State 结构

参考文章

选择 State 结构

构建良好的 state 可以让组件变得易于修改和调试,而不会经常出错。以下是在构建 state 时应该考虑的一些建议。

构建 state 的原则

当编写一个存有 state 的组件时,需要选择使用多少个 state 变量以及它们都是怎样的数据格式。尽管选择次优的 state 结构下也可以编写正确的程序,但有几个原则可以指导做出更好的决策:

  1. 合并关联的 state。如果总是同时更新两个或更多的 state 变量,请考虑将它们合并为一个单独的 state 变量。
  2. 避免互相矛盾的 state。当 state 结构中存在多个相互矛盾或“不一致”的 state 时,就可能为此会留下隐患。应尽量避免这种情况。
  3. 避免冗余的 state。如果能在渲染期间从组件的 props 或其现有的 state 变量中计算出一些信息,则不应将这些信息放入该组件的 state 中。
  4. 避免重复的 state。当同一数据在多个 state 变量之间或在多个嵌套对象中重复时,这会很难保持它们同步。应尽可能减少重复。
  5. 避免深度嵌套的 state。深度分层的 state 更新起来不是很方便。如果可能的话,最好以扁平化方式构建 state。

这些原则背后的目标是 使 state 易于更新而不引入错误。从 state 中删除冗余和重复数据有助于确保所有部分保持同步。这类似于数据库工程师想要 “规范化”数据库结构,以减少出现错误的机会。用爱因斯坦的话说,“让你的状态尽可能简单,但不要过于简单。”

现在让我们来看看这些原则在实际中是如何应用的。

合并关联的 state

有时候可能会不确定是使用单个 state 变量还是多个 state 变量。

你会像下面这样做吗?

const [x, setX] = useState(0);
const [y, setY] = useState(0);

或这样?

const [position, setPosition] = useState({ x: 0, y: 0 });

从技术上讲,可以使用其中任何一种方法。但是,如果某两个 state 变量总是一起变化,则将它们统一成一个 state 变量可能更好。这样就不会忘记让它们始终保持同步,就像下面这个例子中,移动光标会同时更新红点的两个坐标:

import { useState } from 'react';export default function MovingDot() {const [position, setPosition] = useState({x: 0,y: 0});return (<divonPointerMove={e => {setPosition({x: e.clientX,y: e.clientY});}}style={{position: 'relative',width: '100vw',height: '100vh',}}><div style={{position: 'absolute',backgroundColor: 'red',borderRadius: '50%',transform: `translate(${position.x}px, ${position.y}px)`,left: -10,top: -10,width: 20,height: 20,}} /></div>)
}

另一种情况是,将数据整合到一个对象或一个数组中时,不知道需要多少个 state 片段。例如,当有一个用户可以添加自定义字段的表单时,这将会很有帮助。

注意:如果 state 变量是一个对象时,请记住,不能只更新其中的一个字段 而不显式复制其他字段。例如,在上面的例子中,不能写成 setPosition({ x: 100 }),因为它根本就没有 y 属性! 相反,如果想要仅设置 x,则可执行 setPosition({ ...position, x: 100 }),或将它们分成两个 state 变量,并执行 setX(100)

避免矛盾的 state

下面是带有 isSendingisSent 两个 state 变量的酒店反馈表单:

import { useState } from 'react';export default function FeedbackForm() {const [text, setText] = useState('');const [isSending, setIsSending] = useState(false);const [isSent, setIsSent] = useState(false);async function handleSubmit(e) {e.preventDefault();setIsSending(true);await sendMessage(text);setIsSending(false);setIsSent(true);}if (isSent) {return <h1>Thanks for feedback!</h1>}return (<form onSubmit={handleSubmit}><p>How was your stay at The Prancing Pony?</p><textareadisabled={isSending}value={text}onChange={e => setText(e.target.value)}/><br /><buttondisabled={isSending}type="submit">Send</button>{isSending && <p>Sending...</p>}</form>);
}// 假装发送一条消息。
function sendMessage(text) {return new Promise(resolve => {setTimeout(resolve, 2000);});
}

尽管这段代码是有效的,但也会让一些 state “极难处理”。例如,如果忘记同时调用 setIsSentsetIsSending,则可能会出现 isSendingisSent 同时为 true 的情况。组件越复杂,就越难理解发生了什么。

因为 isSendingisSent 不应同时为 true,所以最好用一个 status 变量来代替它们,这个 state 变量可以采取三种有效状态其中之一'typing' (初始), 'sending', 和 'sent':

import { useState } from 'react';export default function FeedbackForm() {const [text, setText] = useState('');const [status, setStatus] = useState('typing');async function handleSubmit(e) {e.preventDefault();setStatus('sending');await sendMessage(text);setStatus('sent');}const isSending = status === 'sending';const isSent = status === 'sent';if (isSent) {return <h1>Thanks for feedback!</h1>}return (<form onSubmit={handleSubmit}><p>How was your stay at The Prancing Pony?</p><textareadisabled={isSending}value={text}onChange={e => setText(e.target.value)}/><br /><buttondisabled={isSending}type="submit">Send</button>{isSending && <p>Sending...</p>}</form>);
}// 假装发送一条消息。
function sendMessage(text) {return new Promise(resolve => {setTimeout(resolve, 2000);});
}

仍然可以声明一些常量,以提高可读性:

const isSending = status === 'sending';
const isSent = status === 'sent';

但它们不是 state 变量,所以不必担心它们彼此失去同步。

避免冗余的 state

如果能在渲染期间从组件的 props 或其现有的 state 变量中计算出一些信息,则不应该把这些信息放到该组件的 state 中。

例如,以这个表单为例。它可以运行,但你能找到其中任何冗余的 state 吗?

import { useState } from 'react';export default function Form() {const [firstName, setFirstName] = useState('');const [lastName, setLastName] = useState('');const [fullName, setFullName] = useState('');function handleFirstNameChange(e) {setFirstName(e.target.value);setFullName(e.target.value + ' ' + lastName);}function handleLastNameChange(e) {setLastName(e.target.value);setFullName(firstName + ' ' + e.target.value);}return (<><h2>Let’s check you in</h2><label>First name:{' '}<inputvalue={firstName}onChange={handleFirstNameChange}/></label><label>Last name:{' '}<inputvalue={lastName}onChange={handleLastNameChange}/></label><p>Your ticket will be issued to: <b>{fullName}</b></p></>);
}

这个表单有三个 state 变量:firstNamelastNamefullName。然而,fullName 是多余的。在渲染期间,始终可以从 firstNamelastName 中计算出 fullName,因此需要把它从 state 中删除。

可以这样做:

import { useState } from 'react';export default function Form() {const [firstName, setFirstName] = useState('');const [lastName, setLastName] = useState('');const fullName = firstName + ' ' + lastName;function handleFirstNameChange(e) {setFirstName(e.target.value);}function handleLastNameChange(e) {setLastName(e.target.value);}return (<><h2>Let’s check you in</h2><label>First name:{' '}<inputvalue={firstName}onChange={handleFirstNameChange}/></label><label>Last name:{' '}<inputvalue={lastName}onChange={handleLastNameChange}/></label><p>Your ticket will be issued to: <b>{fullName}</b></p></>);
}

这里的 fullName 不是 一个 state 变量。相反,它是在渲染期间中计算出的:

const fullName = firstName + ' ' + lastName;

因此,更改处理程序不需要做任何特殊操作来更新它。当调用 setFirstNamesetLastName 时,会触发一次重新渲染,然后下一个 fullName 将从新数据中计算出来。

避免重复的 state

下面这个菜单列表组件可以让你在多种旅行小吃中选择一个:

import { useState } from 'react';const initialItems = [{ title: 'pretzels', id: 0 },{ title: 'crispy seaweed', id: 1 },{ title: 'granola bar', id: 2 },
];export default function Menu() {const [items, setItems] = useState(initialItems);const [selectedItem, setSelectedItem] = useState(items[0]);return (<><h2>What's your travel snack?</h2><ul>{items.map(item => (<li key={item.id}>{item.title}{' '}<button onClick={() => {setSelectedItem(item);}}>Choose</button></li>))}</ul><p>You picked {selectedItem.title}.</p></>);
}

当前,它将所选元素作为对象存储在 selectedItem state 变量中。然而,这并不好:selectedItem 的内容与 items 列表中的某个项是同一个对象。 这意味着关于该项本身的信息在两个地方产生了重复。

为什么这是个问题?让我们使每个项目都可以编辑:

import { useState } from 'react';const initialItems = [{ title: 'pretzels', id: 0 },{ title: 'crispy seaweed', id: 1 },{ title: 'granola bar', id: 2 },
];export default function Menu() {const [items, setItems] = useState(initialItems);const [selectedItem, setSelectedItem] = useState(items[0]);function handleItemChange(id, e) {setItems(items.map(item => {if (item.id === id) {return {...item,title: e.target.value,};} else {return item;}}));}return (<><h2>What's your travel snack?</h2> <ul>{items.map((item, index) => (<li key={item.id}><inputvalue={item.title}onChange={e => {handleItemChange(item.id, e)}}/>{' '}<button onClick={() => {setSelectedItem(item);}}>Choose</button></li>))}</ul><p>You picked {selectedItem.title}.</p></>);
}

请注意,如果首先单击菜单上的“Choose” 然后 编辑它,输入会更新,但底部的标签不会反映编辑内容。 这是因为有重复的 state,并且忘记更新了 selectedItem

尽管也可以更新 selectedItem,但更简单的解决方法是消除重复项。在下面这个例子中,将 selectedId 保存在 state 中,而不是在 selectedItem 对象中(它创建了一个与 items 内重复的对象),然后 通过搜索 items 数组中具有该 ID 的项,以此获取 selectedItem

import { useState } from 'react';const initialItems = [{ title: 'pretzels', id: 0 },{ title: 'crispy seaweed', id: 1 },{ title: 'granola bar', id: 2 },
];export default function Menu() {const [items, setItems] = useState(initialItems);const [selectedId, setSelectedId] = useState(0);const selectedItem = items.find(item =>item.id === selectedId);function handleItemChange(id, e) {setItems(items.map(item => {if (item.id === id) {return {...item,title: e.target.value,};} else {return item;}}));}return (<><h2>What's your travel snack?</h2><ul>{items.map((item, index) => (<li key={item.id}><inputvalue={item.title}onChange={e => {handleItemChange(item.id, e)}}/>{' '}<button onClick={() => {setSelectedId(item.id);}}>Choose</button></li>))}</ul><p>You picked {selectedItem.title}.</p></>);
}

(或者,可以将所选索引保持在 state 中。)

state 过去常常是这样复制的:

  • items = [{ id: 0, title: 'pretzels'}, ...]
  • selectedItem = {id: 0, title: 'pretzels'}

改了之后是这样的:

  • items = [{ id: 0, title: 'pretzels'}, ...]
  • selectedId = 0

重复的 state 没有了,只保留了必要的 state!

现在,如果编辑 selected 元素,下面的消息将立即更新。这是因为 setItems 会触发重新渲染,而 items.find(...) 会找到带有更新文本的元素。不需要在 state 中保存 选定的元素,因为只有 选定的 ID 是必要的。其余的可以在渲染期间计算。

避免深度嵌套的 state

想象一下,一个由行星、大陆和国家组成的旅行计划。可能会尝试使用嵌套对象和数组来构建它的 state,就像下面这个例子:

import { useState } from 'react';
import { initialTravelPlan } from './places.js';function PlaceTree({ place }) {const childPlaces = place.childPlaces;return (<li>{place.title}{childPlaces.length > 0 && (<ol>{childPlaces.map(place => (<PlaceTree key={place.id} place={place} />))}</ol>)}</li>);
}export default function TravelPlan() {const [plan, setPlan] = useState(initialTravelPlan);const planets = plan.childPlaces;return (<><h2>Places to visit</h2><ol>{planets.map(place => (<PlaceTree key={place.id} place={place} />))}</ol></>);
}
// places.js
export const initialTravelPlan = {id: 0,title: '(Root)',childPlaces: [{id: 1,title: 'Earth',childPlaces: [{id: 2,title: 'Africa',childPlaces: [{id: 3,title: 'Botswana',childPlaces: []}, {id: 4,title: 'Egypt',childPlaces: []}]}, {id: 10,title: 'Americas',childPlaces: [{id: 18,title: 'Venezuela',childPlaces: []}]}, {id: 19,title: 'Asia',childPlaces: [{id: 20,title: 'China',childPlaces: []}]}, {id: 26,title: 'Europe',childPlaces: [{id: 27,title: 'Croatia',childPlaces: [],}, {id: 33,title: 'Turkey',childPlaces: [],}]}, {id: 34,title: 'Oceania',childPlaces: [{id: 35,title: 'Australia',childPlaces: [],}]}]}, {id: 42,title: 'Moon',childPlaces: [{id: 43,title: 'Rheita',childPlaces: []}]}]
};

现在,假设想添加一个按钮来删除一个已经去过的地方。会怎么做呢?更新嵌套的 state 需要从更改部分一直向上复制对象。删除一个深度嵌套的地点将涉及复制其整个父级地点链。这样的代码可能非常冗长。

如果 state 嵌套太深,难以轻松更新,可以考虑将其“扁平化”。 这里有一个方法可以重构上面这个数据。不同于树状结构,每个节点的 place 都是一个包含 其子节点 的数组,可以让每个节点的 place 作为数组保存 其子节点的 ID。然后存储一个节点 ID 与相应节点的映射关系。

这个数据重组可能会让你想起看到一个数据库表:

import { useState } from 'react';
import { initialTravelPlan } from './places.js';function PlaceTree({ id, placesById }) {const place = placesById[id];const childIds = place.childIds;return (<li>{place.title}{childIds.length > 0 && (<ol>{childIds.map(childId => (<PlaceTreekey={childId}id={childId}placesById={placesById}/>))}</ol>)}</li>);
}export default function TravelPlan() {const [plan, setPlan] = useState(initialTravelPlan);const root = plan[0];const planetIds = root.childIds;return (<><h2>Places to visit</h2><ol>{planetIds.map(id => (<PlaceTreekey={id}id={id}placesById={plan}/>))}</ol></>);
}
// places.js
export const initialTravelPlan = {0: {id: 0,title: '(Root)',childIds: [1, 42],},1: {id: 1,title: 'Earth',childIds: [2, 10, 19, 26, 34]},2: {id: 2,title: 'Africa',childIds: [3, 4]}, 3: {id: 3,title: 'Botswana',childIds: []},4: {id: 4,title: 'Egypt',childIds: []},10: {id: 10,title: 'Americas',childIds: [18],   },18: {id: 18,title: 'Venezuela',childIds: []},19: {id: 19,title: 'Asia',childIds: [20],   },20: {id: 20,title: 'China',childIds: []},26: {id: 26,title: 'Europe',childIds: [27, 33],   },27: {id: 27,title: 'Croatia',childIds: []},33: {id: 33,title: 'Turkey',childIds: []},34: {id: 34,title: 'Oceania',childIds: [35],   },35: {id: 35,title: 'Australia',childIds: []},42: {id: 42,title: 'Moon',childIds: [43]},43: {id: 43,title: 'Rheita',childIds: []},
};

现在 state 已经“扁平化”(也称为“规范化”),更新嵌套项会变得更加容易。

现在要删除一个地点,只需要更新两个 state 级别:

  • 父级 地点的更新版本应该从其 childIds 数组中排除已删除的 ID。
  • 其根级“表”对象的更新版本应包括父级地点的更新版本。

下面是展示如何处理它的一个示例:

import { useState } from 'react';
import { initialTravelPlan } from './places.js';export default function TravelPlan() {const [plan, setPlan] = useState(initialTravelPlan);function handleComplete(parentId, childId) {const parent = plan[parentId];// 创建一个其父级地点的新版本// 但不包括子级 ID。const nextParent = {...parent,childIds: parent.childIds.filter(id => id !== childId)};// 更新根 state 对象...setPlan({...plan,// ...以便它拥有更新的父级。[parentId]: nextParent});}const root = plan[0];const planetIds = root.childIds;return (<><h2>Places to visit</h2><ol>{planetIds.map(id => (<PlaceTreekey={id}id={id}parentId={0}placesById={plan}onComplete={handleComplete}/>))}</ol></>);
}function PlaceTree({ id, parentId, placesById, onComplete }) {const place = placesById[id];const childIds = place.childIds;return (<li>{place.title}<button onClick={() => {onComplete(parentId, id);}}>Complete</button>{childIds.length > 0 &&<ol>{childIds.map(childId => (<PlaceTreekey={childId}id={childId}parentId={id}placesById={placesById}onComplete={onComplete}/>))}</ol>}</li>);
}

确实可以随心所欲地嵌套 state,但是将其“扁平化”可以解决许多问题。这使得 state 更容易更新,并且有助于确保在嵌套对象的不同部分中没有重复。

有时候,也可以通过将一些嵌套 state 移动到子组件中来减少 state 的嵌套。这对于不需要保存的短暂 UI 状态非常有效,比如一个选项是否被悬停。

摘要

  • 如果两个 state 变量总是一起更新,请考虑将它们合并为一个。
  • 仔细选择 state 变量,以避免创建“极难处理”的 state。
  • 用一种减少出错更新的机会的方式来构建 state。
  • 避免冗余和重复的 state,这样就不需要保持同步。
  • 除非特别想防止更新,否则不要将 props 放入 state 中。
  • 对于选择类型的 UI 模式,请在 state 中保存 ID 或索引而不是对象本身。
  • 如果深度嵌套 state 更新很复杂,请尝试将其展开扁平化。

相关文章:

React 18 选择 State 结构

参考文章 选择 State 结构 构建良好的 state 可以让组件变得易于修改和调试&#xff0c;而不会经常出错。以下是在构建 state 时应该考虑的一些建议。 构建 state 的原则 当编写一个存有 state 的组件时&#xff0c;需要选择使用多少个 state 变量以及它们都是怎样的数据格…...

LNMT与动静分离

目录 一、LNMT 一、部署tomcat 二、部署nginx 三、部署mariadb 四、配置nginx 二、操作流程及步骤 一、在第一台机器上进入 vim /etc/nginx/nginx.conf 更改配置文件 二、并查看端口是否成功启动 三、验证 四、再次来到网页验证 五、动静分离&#xff08;修改配置…...

【java】LinkedList 和 ArrayList的简介与对比

Java LinkedList和 ArrayList 在使用上&#xff0c;几乎是一样的。由于LinkedList是基于双向链表的&#xff0c;会多出list.getFirst();获取头部元素等方法 链表&#xff08;Linked list&#xff09;是一种常见的基础数据结构&#xff0c;是一种线性表&#xff0c;但是并不会按…...

机器学习基础14-算法调参(基于印第安糖尿病Pima数据集)

机器学习的模型都是参数化的&#xff0c;可以通过调参来提高模型的准确度。 模型有很多参数&#xff0c;如何找到最佳的参数组合&#xff0c;可以把它当作一个查询问题来处理&#xff0c;但是调整参数到何时为止呢&#xff1f;应该遵循偏差和方差协调的原则。 接下来将介绍在 s…...

ASUS华硕天选4笔记本电脑FA507XV原厂Windows11系统22H2

天选四FA507X原装系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件 华硕电脑管家、奥创控制中心等预装程序&#xff0c;恢复出厂状态W11 链接&#xff1a;https://pan.baidu.com/s/1SPoFW7wR5KawGu-yMckNzg?pwdayxd 提取码&#xff1a;ayxd...

IET独立出版 | EI检索 | 2023年第三届机械、航空航天与汽车工程国际会议

会议简介 Brief Introduction 2023年第三届机械、航空航天与汽车工程国际会议&#xff08;CMAAE 2023&#xff09; 会议时间&#xff1a;2023年12月8 -10日 召开地点&#xff1a;中国南京 大会官网&#xff1a;www.cmaae.org 航天是当今世界最具挑战性和广泛带动性的高技术领域…...

【Pytorch】CUDA error: no kernel image is available for execution on the device

记录一下pytorch安装的cuda版本和GPU cuda不一致的解决。 RuntimeError: CUDA error: no kernel image is available for execution on the device 一般就是pytorch和cuda安装的不匹配。 如果我安装的torch配的cuda信息如下&#xff0c; torch.__version__: 1.8.1cu102 tor…...

dolphinschedule配置企微告警服务(WeChat群组)

一、前置说明 ds配置好工作流后&#xff0c;比较重要的一个就是上线后的监控报警服务&#xff0c;如果你是基于企微作为协同办公的&#xff0c;WeChat群组预警必须是要安排上的&#xff0c;文章基于自建应用配合群组方式构建预警群&#xff0c;接入后&#xff0c;任务成功或者…...

Git中smart Checkout与force checkout

Git中smart Checkout与force checkout 使用git进行代码版本管理,当我们切换分支有时会遇到这样的问题&#xff1a; 这是因为在当前分支修改了代码&#xff0c;但是没有commit,所以在切换到其他分支的时候会弹出这个窗口&#xff0c; 提示你选force checkout或者smart checko…...

Java“牵手”1688商品跨境属性数据,1688API接口申请指南

1688平台商品详情跨境属性数据接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取1688商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片&#xff0c;重量&#xff0c;详情描述等详细信息 。 获取商品详情接口API是一种用于…...

Win解答 | 解决键盘中 字母+空格 导致的输入法弹窗导致的一系列问题

近三个月来&#xff0c;一直都有一个键盘组合键的问题影响我的电脑使用&#xff0c;不管是打字还是打游戏&#xff0c;都会出现按键盘的 字母空格 弹出一个特殊符号的候选框&#xff0c;如下图所示 图片中为 S空格 所出现的弹窗 一个看似方便&#xff0c;实则难受的功能 其实打…...

WPF读取dicom序列:实现上一帧、下一帧、自动播放、暂停

一、整体设计概况 创建WPF程序使用.Net Framework4.8定义Image控件展示图像增加标签展示dcm文件信息规划按钮触发对应的事件:上一帧、下一帧、自动播放、暂停、缩放、播放速率二、页面展示 三、代码逻辑分析 Windows窗体加载Loaded事件:生成初始图像信息Windows窗体加载Mous…...

homeassistant ubuntu自启动 网络设置

命令行安装virtualbox 或者安装包 hass官网下载 haos_ova-10.4.vdi virtualbox 装hass 最少2G内存 其他省略 自启动&#xff1a; gnome-session-properties 添加 VBoxManage startvm hass --type headless hass为自己的虚拟机名字 网络配置如下&#xff1a; 要全部打开...

生成式AI背景下编程工作者的技术和高级软考理论的演进融合之路

思考背景 近两次软考&#xff0c;我都参与了&#xff0c;2022年11月参加的是系统架构师的考试&#xff0c;2023年5月参加的是系统分析师的考试&#xff0c;去年参加系统架构是考试是完全的裸考和第一次考&#xff0c;成绩是选择题39&#xff0c;综合题46和论文48分&#xff0c…...

RabbitMQ的镜像队列

镜像队列 如果 RabbitMQ 集群中只有一个 Broker 节点&#xff0c;那么该节点的失效将导致整体服务的临时性不可用&#xff0c;并且也可能会导致消息的丢失。可以将所有消息都设置为持久化&#xff0c;并且对应队列的durable 属性也设置为 true &#xff0c;但是这样仍然无法…...

【Spring Boot】数据库持久层框架MyBatis — Spring Boot构建MyBatis应用程序

Spring Boot构建MyBatis应用程序 Spring Boot是用于快速构建Spring应用程序的框架。MyBatis是一种Java持久化框架&#xff0c;可以帮助开发人员轻松地管理数据库。将Spring Boot与MyBatis结合使用可以使开发人员更容易地创建和管理数据库应用程序。 以下是使用Spring Boot构建…...

【校招VIP】专业课考点之session cookie

考点介绍&#xff1a; 测试工作中我们经常会听到这两个词&#xff0c;作为测试一定要理解这两个概念&#xff0c;对于测试应用的接口、业务理解很有帮助。需要了解Cookie和Session的作用、原理和两者的区别。 『专业课考点之session cookie』相关题目及解析内容可点击文章末尾…...

IDEA集成Git相关操作知识(pull、push、clone)

一&#xff1a;集成git 1&#xff1a;初始化git&#xff08;新版本默认初始化&#xff09; 老版本若没有&#xff0c;点击VCS&#xff0c;选中import into Version Controller中的Create git Repository(创建git仓库)&#xff0c;同理即可出现git符号。 也可查看源文件夹有没有…...

Springboot 整合 Redis配置

RedisService接口 import java.util.List; import java.util.Map; import java.util.Set;/*** Redis操作Service* Created by macro on 2020/3/3.*/ public interface RedisService {/*** 保存属性*/void set(String key, Object value, long time);/*** 保存属性*/void set(St…...

Spark 启动时,报JAVA_HOME is not set

文章目录 1、报错内容2、解决方式3、再次启动Spark集群 1、报错内容 Spark启动时报错&#xff1a; hadoop104: JAVA_HOME is not set2、解决方式 解决方式&#xff1a; 打开启动配置文件 cd /opt/module/spark-standalone/sbin/ vim spark-config.sh配置Java的环境变量 …...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...