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

react中的useState和useImmer的用法

文章目录

  • 一、useState
    • 1. 更新基本类型数据
    • 2. 更新对象
    • 3. 更新嵌套对象
    • 4. 更新数组
    • 5.更新数组对象
  • 二、Immer
    • 1. 什么是Immer
    • 2. 使用use-immer更新嵌套对象
    • 3. 使用useImmer更新数组内部的对象

一、useState

react中文官网教程

1. 更新基本类型数据

在函数式组件中,可以使用 useState 这个 Hook 来定义和管理组件的状态。useState 接受一个初始状态作为参数,并返回一个包含 state 和更新 state 的方法的数组。

下面是一个例子,展示了如何在函数式组件中定义自己的 state:

import React, { useState } from "react";function MyComponent() {// 定义一个名为 count 的 state 变量,并将初始值设置为 0const [count, setCount] = useState(0);const handleClick = () => {setCount(count + 1);};return (<div><p>Count: {count}</p><button onClick={handleClick}>Increase Count</button></div>);
}export default MyComponent;

在上面的例子中,我们使用 useState 创建了一个名为 count 的状态变量,并将其初始值设为 0。然后,我们将 count 的值展示在 <p> 元素中,并在按钮的点击事件中调用 setCount 来更新 count 的值。

每当我们调用 setCount 来更新 count 的值时,React 会重新渲染组件并传递更新后的值给 count

2. 更新对象

在函数式组件中使用useState更新state中的对象可以通过以下步骤:

  1. 导入useState:
import React, { useState } from 'react';
  1. 创建一个对象作为初始状态(state):
const initialState = { name: 'John', age: 30, email: 'john@example.com' };
  1. 在组件内部使用useState钩子声明state:
const [person, setPerson] = useState(initialState);

这里person是状态对象,setPerson是一个更新状态的函数。useState(initialState)是useState的初始值参数。

  1. 在组件中使用状态对象:
return (<div><p>Name: {person.name}</p><p>Age: {person.age}</p><p>Email: {person.email}</p></div>
);
  1. 使用setPerson函数来更新状态对象的值:
const updateEmail = () => {setPerson({ ...person, email: 'updated@example.com' });
};

这里使用了ES6的展开语法(spread syntax)来复制现有的person对象,并更新email属性的值。

  1. 在组件中调用updateEmail函数来更新状态:
<button onClick={updateEmail}>Update Email</button>

完整的示例代码如下:

import React, { useState } from 'react';const App = () => {const initialState = { name: 'John', age: 30, email: 'john@example.com' };const [person, setPerson] = useState(initialState);const updateEmail = () => {setPerson({ ...person, email: 'updated@example.com' });};return (<div><p>Name: {person.name}</p><p>Age: {person.age}</p><p>Email: {person.email}</p><button onClick={updateEmail}>Update Email</button></div>);
};export default App;

通过点击"Update Email"按钮,可以更新email属性的值为"updated@example.com"。

在React的函数式组件中使用useState来更新一个对象的state时,有几个注意点需要特别注意

  1. useState函数仅仅是按照传入的初始值来初始化state,并不会合并对象。因此,在更新state时,需要先使用解构方式取出旧的对象属性值,然后再设置新的对象属性值。

  2. 由于useState是按照值的变化来判断是否重新渲染组件的,因此在更新state时,需要保证每一次更新都是返回一个新的对象。直接对原对象进行修改并返回会导致state没有发生变化,从而不会触发重新渲染。

  3. 可以使用展开运算符扩展现有对象,再进行属性的更改。这样可以确保每次都返回一个新的对象。

为什么要注意这些点呢?

首先,useState是基于值的比较来判断是否重新渲染组件的,如果不注意每次都返回一个新的对象,可能会导致state没有发生变化,从而不会触发重新渲染,无法更新组件视图。

其次,由于函数式组件没有实例的概念,每次组件渲染都是独立的,因此无法像类组件中使用this.setState那样自动合并对象属性。因此,在更新state时,需要手动合并旧的对象属性值和新的对象属性值,以确保不丢失任何旧的state属性。

最后,使用展开运算符扩展对象的方式可以确保每次都返回一个全新的对象,这样可以避免直接对原对象进行修改而导致state没有发生变化的问题。

3. 更新嵌套对象

在React的函数式组件中使用useState更新state中的嵌套对象,可以使用扩展运算符(spread operator)来实现。

举例说明,假设有一个包含嵌套对象的state,如下所示:

const [state, setState] = useState({name: "John",age: 30,address: {street: "123 Main St",city: "New York",state: "NY"}
});

要更新state中的嵌套对象,可以使用useState的setState函数,传递一个新的对象,并使用扩展运算符将原有的state进行展开,再覆盖需要更新的属性。例如,要更新address对象的city属性,可以使用以下代码:

setState({...state,address: {...state.address,city: "Los Angeles"}
});

上面的代码首先使用扩展运算符将原有的state展开,然后再针对需要更新的嵌套对象进行展开,并更新特定的属性。在本例中,我们更新了address对象的city属性,将其值从"New York"更新为"Los Angeles"。

完整的示例代码如下所示:

import React, { useState } from "react";function App() {const [state, setState] = useState({name: "John",age: 30,address: {street: "123 Main St",city: "New York",state: "NY"}});const updateCity = () => {setState({...state,address: {...state.address,city: "Los Angeles"}});};return (<div><p>Name: {state.name}</p><p>Age: {state.age}</p><p>Street: {state.address.street}</p><p>City: {state.address.city}</p><p>State: {state.address.state}</p><button onClick={updateCity}>Update City</button></div>);
}export default App;

在上述示例中,我们首先使用useState定义了包含嵌套对象的state,然后在组件中显示了state中的属性。最后,我们使用一个按钮来调用updateCity函数,该函数会更新state中的嵌套对象。点击按钮后,更新后的city属性值将显示为"Los Angeles"。

4. 更新数组

在函数式组件中使用useState来更新state中的数组,可以通过结构赋值的方式获取数组和更新数组的函数。一般情况下,使用useState更新数组时需要注意以下几点:

  1. 为了保持state的不可变性,应该使用数组的展开运算符(spread operator)来创建一个新的数组。

  2. 当更新数组时,需要将要更新的元素和其余元素区分开来。通常使用Array.map函数来遍历数组,并找到要更新的元素。

  3. 可以使用Array.filter函数过滤数组中的元素,从而可以删除特定的元素。

  4. 注意在更新数组时,在判断相等性时使用严格相等运算符(===),而不是用“浅比较”运算符(==)
    在这里插入图片描述

下面是一个更新数组的例子:

import React, { useState } from "react";function Example() {const [list, setList] = useState([1, 2, 3, 4, 5]);const handleUpdate = () => {// 通过展开运算符创建一个新的数组,并更新数组的第一个元素setList([...list.slice(0, 1), 100, ...list.slice(2)]);};const handleDelete = (item) => {// 使用filter过滤数组,删除特定的元素setList(list.filter((el) => el !== item));};return (<div><ul>{list.map((item) => (<li key={item}>{item}<button onClick={() => handleDelete(item)}>删除</button></li>))}</ul><button onClick={handleUpdate}>更新</button></div>);
}export default Example;

在这个例子中,list是一个包含数字的数组。点击列表项后的“删除”按钮会删除相应的元素,点击“更新”按钮会将数组的第一个元素更新为100。每次更新数组时,使用展开运算符创建一个新的数组,并把更新的元素插入到适当的位置,这样可以保持state的不可变性。在删除元素时,使用filter函数过滤掉特定的元素。

5.更新数组对象

在函数式组件中使用 useState 来更新 state 数组中的内部对象,可以使用解构赋值的方式来获取数组中的指定对象,并使用 useState 来更新该对象的属性。

首先,在函数式组件中使用 useState 定义一个状态变量,可以设置初始状态为一个包含内部对象的数组。例如,使用以下代码定义一个状态变量 items,并设置初始状态为一个包含两个内部对象的数组:

const [items, setItems] = useState([{ name: "apple", quantity: 1 },{ name: "banana", quantity: 2 }
]);

然后,通过解构赋值的方式获取数组中的指定对象,并使用 useState 更新该对象的属性。例如,通过以下代码获取数组中的第一个对象 item 并更新其 name 属性:

const [item, setItem] = useState(items[0]);const handleChangeName = () => {setItem(prevItem => ({ ...prevItem, name: "orange" }));
};

在上述代码中,setItem 函数通过接收一个回调函数来更新 item 对象的属性。该回调函数使用展开运算符 ... 将之前的属性拷贝到一个新的对象中,并更新 name 属性为 "orange"

需要注意的是,在更新数组时,不能直接修改数组中的对象。要更新数组中的对象,需要先拷贝数组,然后再更新其中的对象。可以使用 Array.map() 方法来拷贝数组并更新其中的对象。例如,使用以下代码将数组中的第一个对象的 name 属性改为 "orange"

const updatedItems = items.map((item, index) => {if (index === 0) {return { ...item, name: "orange" };}return item;
});setItems(updatedItems);

上述代码中,Array.map() 方法遍历数组,当索引为 0 的时候,返回一个新的对象,并更新其 name 属性为 "orange";否则,返回原来的对象。然后,将得到的新数组 updatedItems 设置为新的状态值。

二、Immer

1. 什么是Immer

Immer是一个JavaScript库,用于管理不可变状态。它通过基于原始状态创建一个新的状态树来实现不可变性。它提供了一种简单而直观的方式来处理复杂的状态更新逻辑,使代码更易于理解和维护。Immer可以与任何JavaScript框架或库一起使用,并且对于处理大型数据结构和深层嵌套的对象非常有用。它是一个流行的工具,用于管理JavaScript应用程序中的状态。

在React的函数式组件中,推荐使用Immer来处理复杂的数据state,特别是深层嵌套的数组对象,有以下几个原因:

  1. 操作不可变数据更加方便:Immer提供了一种简洁的方式来直接对不可变数据进行修改。通过使用Immer的produce函数,可以在不直接修改原始数据的情况下,创建一个可变的草稿副本,并且在草稿上进行所有的更改操作。这样可以避免因为直接修改原始数据而导致的引用问题和副作用问题。

  2. 性能优化:Immer采用了一种优化技术,称为“结构共享”,它能够在不实际复制数据的情况下实现不可变数据的修改。这种技术可以大大提高性能,特别是对于大型、深层嵌套的数据结构。

  3. 减少模板嵌套深度:在处理深层嵌套的数组对象时,使用Immer可以减少模板嵌套的深度。因为Immer提供了一种更简洁、更直观的方式来修改深层嵌套的数据,这能够提高代码的可读性和可维护性。

总之,使用Immer可以帮助我们更方便地处理复杂的数据state,尤其是深层嵌套的数组对象。它简化了对不可变数据的操作,并提供了性能优化的机制,使得我们能够更加高效地开发React应用。

2. 使用use-immer更新嵌套对象

在React的函数式组件中,可以使用use-immer库来更新嵌套对象的state。use-immer是基于Immer库的React Hook封装,它可以方便地进行不可变状态更新。

以下是一个示例,展示如何使用use-immer更新嵌套对象的state:

首先,安装use-immer库:

npm install use-immer

然后,导入useImmer函数并在函数式组件中使用它:

import React, { useState } from 'react';
import { useImmer } from 'use-immer';function App() {const [state, setState] = useImmer({user: {name: 'John',age: 25}});// 更新嵌套对象的示例函数const updateUserName = () => {setState(draft => {draft.user.name = 'Tom';});};return (<div><h1>{state.user.name}</h1><p>{state.user.age}</p><button onClick={updateUserName}>Update Name</button></div>);
}export default App;

在上面的示例中,我们使用useState和useImmer来声明和初始化state。state是一个嵌套对象,包含一个user对象。然后,我们在updateUserName函数中使用setState函数来更新嵌套对象的state。在setState的回调函数中,我们可以使用draft参数来修改状态。

使用use-immer库的好处是,我们可以在回调函数中直接修改draft对象,就像在原始状态上进行修改一样。useImmer会负责处理不可变性,最终生成一个新的状态,并将其应用于组件。

以上是使用use-immer库在React的函数式组件中更新嵌套对象状态的示例。可以根据实际需求进行相应的修改和扩展。

3. 使用useImmer更新数组内部的对象

可以使用useImmer hook结合immer来更新函数式组件中数组内部的对象。useImmer hook是在React中使用Immer库的推荐方式。

以下是一个示例,说明如何使用useImmer更新数组内部的对象:

import React, { useState } from 'react';
import { useImmer } from 'use-immer';const MyComponent = () => {// 使用useState hook创建数组状态const [data, setData] = useState([{ id: 1, name: 'John' },{ id: 2, name: 'Jane' },{ id: 3, name: 'Bob' },]);// 使用useImmer hook创建可变的数据副本draft和更新函数setDraftconst [draft, setDraft] = useImmer(data);// 更新对象的名称const updateName = (id, name) => {setDraft(draft => {// 使用immer的produce函数来更新draftconst item = draft.find(item => item.id === id);if (item) {item.name = name;}});};return (<div>{draft.map(item => (<div key={item.id}><span>{item.name}</span>{/* 在组件中触发更新名称的函数 */}<button onClick={() => updateName(item.id, 'Updated Name')}>Update Name</button></div>))}</div>);
};export default MyComponent;

在上面的代码中,我们首先使用useState hook创建了一个数组状态data,然后使用useImmer hook创建了一个可变的数据副本draft和一个更新函数setDraft。在更新函数中,我们使用immer的produce函数来更新draft,修改特定ID对应的对象的名称。

在组件的返回值中,我们使用draft.map循环遍历数组内部的对象,显示每个对象的名称,并使用按钮来触发更新的函数。

当你点击"Update Name"按钮时,会更新draft中特定ID对应的对象的名称,由于draft是可变的,所以React会自动更新组件的渲染。

相关文章:

react中的useState和useImmer的用法

文章目录 一、useState1. 更新基本类型数据2. 更新对象3. 更新嵌套对象4. 更新数组5.更新数组对象 二、Immer1. 什么是Immer2. 使用use-immer更新嵌套对象3. 使用useImmer更新数组内部的对象 一、useState react中文官网教程 1. 更新基本类型数据 在函数式组件中&#xff0c…...

Can‘t compile code “launch: program <program_path> does not exist “

StackOverflow上有一个类似的提问 我的情况很特殊&#xff0c;上面的回答没有解决我的问题&#xff0c;最后我发现是我的cpp文件名称为数字开头&#xff08;类似于1_floy.cpp&#xff09;&#xff0c;把名字里的数字挪到后面就好了。。。。。...

Mac电脑上升级nodejs

第一步&#xff0c;先查看本机node.js版本&#xff1a; node -v 第二步&#xff0c;清除node.js的cache&#xff1a; sudo npm cache clean -f 第三步&#xff0c;安装 n 工具&#xff0c;这个工具是专门用来管理node.js版本的&#xff0c;别怀疑这个工具的名字&#xff0c…...

基于单片机的太阳跟踪系统的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、设计的主要内容二、硬件电路设计2.1跟踪控制方案的选择2.1.1跟踪系统坐标系的选择2.2系统总体设计及相关硬件介绍…...

V3Det大规模词汇视觉检测数据集与LaRS海上全景障碍物检测数据集

V3Det与LaRS是ICCV2023上发表的数据集工作&#xff0c;规模都比较大&#xff0c;后续有可能会用到&#xff0c;因此记录下来。 V3Det: Vast Vocabulary Visual Detection Dataset Paper: https://arxiv.org/abs/2304.03752 URL: https://v3det.openxlab.org.cn/ 在现实世界中…...

ubuntu(18.04) 安装 blast

1、下载 https://ftp.ncbi.nlm.nih.gov/blast/executables/blast/LATEST/2、解压&#xff0c;配置环境变量 tar zvxf ncbi-blast-2.14.1-x64-linux.tar.gz解压后改名为 blast 配置环境变量&#xff0c;可以不配置 使用的时候直接绝对路径使用 vim ~/.bashrc 将下面添加道最…...

3.2每日一题(定积分求抽水做工问题)

1、画图&#xff0c;把题目的容器画出来&#xff1a;球形容器&#xff0c;半径为R 2、根据容器的形状进行分析&#xff1a; 抽水的实质是不同深度的水抽出去走的位移是不一样的>抽水的过程 &#xff1a; &#xff08;1&#xff09;先考虑深度为 x到xdx 的薄层水抽出去做多少…...

c语言基础:L1-063 吃鱼还是吃肉

国家给出了 8 岁男宝宝的标准身高为 130 厘米、标准体重为 27 公斤&#xff1b;8 岁女宝宝的标准身高为 129 厘米、标准体重为 25 公斤。 现在你要根据小宝宝的身高体重&#xff0c;给出补充营养的建议。 输入格式&#xff1a; 输入在第一行给出一个不超过 10 的正整数 N&am…...

<if> 标签中使用了不正确的语法。在 XML 中,<if> 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错

标签中使用了不正确的语法。在 XML 中&#xff0c; 标签不需要使用 <![CDATA[ ... ]]> 将条件语句包装起来。 否则会报错...

Ubuntu 诞生 19 年

导读2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 作为 Ubuntu 第一个版本&#xff0c;4.10 问世后立刻受到广大 Linux 用户欢迎。它搭载了当时最新的 GNOME 2.8 桌面环境&#xff0c;以及一系列实用软件&#xff0c;比如 Mozilla…...

JVM进阶(3)

一)什么是垃圾&#xff1f; 垃圾指的是在应用程序中没有任何指针指向的对象&#xff0c;这个对象就是需要被回收的垃圾&#xff0c;如果不及时的针对内存中的垃圾进行清理&#xff0c;那么这些垃圾对象所占用的内存空间可能一直保留到应用程序结束&#xff0c;被保留的空间无法…...

Qt QWidget、QDialog、QMainWindow的区别

QWidget QWidget是Qt框架中最基础的窗口类&#xff0c;可以理解为用户界面的最基本单元。QWidget类提供了一个空白窗口&#xff0c;可以通过继承该类来创建自定义的窗口类。QWidget类提供了基本的窗口属性和方法&#xff0c;如大小、位置、标题、图标等。 QDialog QDialog是…...

软考 系统架构设计师系列知识点之设计模式(10)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之设计模式&#xff08;9&#xff09; 所属章节&#xff1a; 老版&#xff08;第一版&#xff09;教材 第7章. 设计模式 第2节. 设计模式实例 相关试题 9. 某软件公司欲设计一款图像处理软件&#xff0c;帮助用户对拍…...

【python爬虫】设计自己的爬虫 1. request封装

通过requests.session().request 封装request方法 考虑到请求HTTP/2.0 同时封装httpx 来处理HTTP/2.0的请求 封装requests # 遇到请求失败的情况时 重新请求&#xff0c;请求5次等待2s retry(stop_max_attempt_number5, retry_on_resultlambda re_data: re_data is None, wai…...

8.0 新特性 - innodb_ddl_threads

前言 MySQL 8.0.27 引入了一个新变量来控制 InnoDB 可用于创建&#xff08;排序和构建&#xff09;二级索引的最大并行线程数&#xff1a;innodb_ddl_threads 通过调整该参数&#xff0c;可以提升二级索引的创建速度。 参数介绍 1. innodb_ddl_threads 创建二级索引时&…...

pgAdmin 4 v7.8 发布,PostgreSQL 开源图形化管理工具

导读pgAdmin 是 PostgreSQL 领先的开源图形化管理工具。pgAdmin 4 旨在满足新手和有经验的 Postgres 用户的需求&#xff0c;提供强大的图形界面&#xff0c;简化了数据库对象的创建、维护和使用。 pgAdmin 开发团队日前发布了 pgAdmin 4 v7.8 版本&#xff0c;这个版本包括 21…...

Realrek 2.5G交换机 8+1万兆光RTL8373-VB-CG方案简介

新一代2.5G交换机方案RTL8373-VB-CG可以提供4中不同形态 a. 52.5G 电口110G光》RTL8373 b. 52.5G 电口110G电》RTL83738261 c. 82.5G 电口110G光》RTL83738224 d.82.5G 电口110G电口》RTL837382248261 1.概述 Realtek RTL8373-CG是一款低功耗、高性能、高度集成的八端口2.5G和一…...

Linux命令随笔

文章目录 grep命令 grep命令 例如&#xff0c;在Linux系统中&#xff0c;要在当前目录下的所有文件中搜索包含字符串"hello"的行&#xff0c;并显示文件名&#xff0c;可以使用以下命令&#xff1a; grep -r "hello" .其中&#xff0c;"."表示…...

最新版scene-builder安装

JavaFX Scene Builder是一个可视化的布局工具&#xff0c;用于设计JavaFX用户界面。它允许开发人员使用拖放和可视化的方式创建和编辑JavaFX界面&#xff0c;而无需直接编写代码。 JavaFX Scene Builder提供了一个直观的界面&#xff0c;让开发人员可以轻松地创建和修改JavaFX…...

直击电商商城内核!一站式解决方案

作为一家深耕电商运营多年的软件开发公司&#xff0c;我们拥有先进的轻量级电商中台系统&#xff0c;且100%开源&#xff0c;包含B2C、B2B2C、S2B2C、O2O和社区团购等多种商业模式&#xff0c;无论在技术、业务架构、功能、设计还是售后支持上&#xff0c;我们都秉承着追求极致…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...