六十天前端强化训练之第十七天React Hooks 入门:useState 深度解析

news2025/3/16 11:33:51

=====欢迎来到编程星辰海的博客讲解======

看完可以给一个免费的三连吗,谢谢大佬!

目录

一、知识讲解

1. Hooks 是什么?

2. useState 的作用

3. 基本语法解析

4. 工作原理

5. 参数详解

a) 初始值设置方式

b) 更新函数特性

6. 注意事项

7. 类组件对比

8. 常见问题解答

二、核心代码示例

三、实现效果

四、学习要点总结

五、扩展阅读推荐

官方文档

优质文章

推荐学习路径

进阶资源

六、实践步骤

一、表单输入控制

二、动态列表组件

三、购物车组件(复杂状态)

四、自定义Hook:useCart

推荐练习项目:


一、知识讲解

1. Hooks 是什么?

React Hooks 是 React 16.8 引入的革命性特性,它允许开发者在函数组件中使用状态(state)和其他 React 特性。Hooks 的诞生解决了以下问题:

  • 类组件中生命周期函数带来的逻辑分散
  • 高阶组件带来的嵌套地狱(Wrapper Hell)
  • 函数组件无法使用状态的局限
  • 状态逻辑难以复用的问题

2. useState 的作用

useState 是最基础且重要的 Hook,它让函数组件具备管理局部状态的能力。其核心功能包括:

  • 声明组件内部状态
  • 提供状态更新方法
  • 触发组件重新渲染
  • 保持状态在多次渲染间的持久性

3. 基本语法解析

JAVASCRIPT

const [state, setState] = useState(initialState);

  • initialState:状态的初始值,可以是任何数据类型
  • state:当前状态值
  • setState:用于更新状态的函数

4. 工作原理

  • 初始化阶段:组件首次渲染时,useState 会读取初始值并保存
  • 更新阶段:调用 setState 后:
    1. 将新值加入更新队列
    2. 触发组件重新渲染
    3. 在下次渲染时返回更新后的状态
  • 渲染机制:每次渲染都有独立的状态快照(闭包特性)

5. 参数详解

a) 初始值设置方式

JAVASCRIPT

// 直接值初始化
const [count, setCount] = useState(0);

// 函数式初始化(惰性初始化)
const [count, setCount] = useState(() => {
  const initialValue = calculateExpensiveValue();
  return initialValue;
});
b) 更新函数特性
  • 支持直接赋值更新:

    JAVASCRIPT

    setCount(5);
    
  • 支持函数式更新(推荐用于依赖前值的场景):

    JAVASCRIPT

    setCount(prevCount => prevCount + 1);
    

6. 注意事项

  • 异步更新:状态更新是异步的,不能立即获取到新值
  • 合并更新:React 会自动合并多个 setState 调用
  • 性能优化:使用函数式更新避免闭包陷阱
  • 不可变原则:始终返回新值而不是修改原值

7. 类组件对比

特性类组件函数组件 + useState
状态初始化constructoruseState 参数
状态更新方式this.setState()setState 函数
状态访问this.state直接使用状态变量
生命周期依赖需要无需
代码组织分散在各个生命周期方法中逻辑集中

8. 常见问题解答

Q:useState 和类组件的 state 有何不同?
A:useState 不会自动合并对象类型的状态,需要手动合并

Q:为什么 setCount(count + 1) 在异步操作中不可靠?
A:由于闭包特性,异步回调中的 count 可能不是最新值,应该使用函数式更新

Q:可以在条件语句中使用 useState 吗?
A:不行,所有 Hooks 都必须保证每次渲染的调用顺序一致

Q:如何存储复杂对象?

JAVASCRIPT

const [user, setUser] = useState({
  name: 'John',
  age: 25,
  address: {
    city: 'New York',
    zip: '10001'
  }
});

// 正确更新方式
setUser(prev => ({
  ...prev,
  age: 26,
  address: {
    ...prev.address,
    zip: '10002'
  }
}));

二、核心代码示例

JSX

import React, { useState } from 'react';

function Counter() {
  // 声明状态变量 count 及其更新函数 setCount
  // 初始值设为 0
  const [count, setCount] = useState(0);

  // 定义增加计数器的方法
  const increment = () => {
    // 使用函数式更新确保基于最新状态值
    setCount(prevCount => prevCount + 1);
  };

  // 定义减少计数器的方法
  const decrement = () => {
    setCount(prevCount => prevCount - 1);
  };

  // 定义重置计数器的方法
  const reset = () => {
    setCount(0);
  };

  return (
    <div style={styles.container}>
      <h2>当前计数: {count}</h2>
      <div style={styles.buttonGroup}>
        {/* 绑定点击事件 */}
        <button style={styles.button} onClick={increment}>+</button>
        <button style={styles.button} onClick={decrement}>-</button>
        <button style={styles.button} onClick={reset}>重置</button>
      </div>
      
      {/* 条件渲染提示信息 */}
      {count >= 10 && <p style={styles.tip}>计数已经超过10啦!</p>}
    </div>
  );
}

// 样式对象
const styles = {
  container: {
    textAlign: 'center',
    padding: '2rem',
    backgroundColor: '#f0f0f0',
    borderRadius: '8px',
    maxWidth: '400px',
    margin: '2rem auto'
  },
  buttonGroup: {
    display: 'flex',
    justifyContent: 'center',
    gap: '1rem',
    marginTop: '1rem'
  },
  button: {
    padding: '0.5rem 1rem',
    fontSize: '1.2rem',
    cursor: 'pointer',
    backgroundColor: '#2196f3',
    color: 'white',
    border: 'none',
    borderRadius: '4px',
    transition: 'background-color 0.3s'
  },
  tip: {
    color: '#d32f2f',
    marginTop: '1rem',
    fontWeight: 'bold'
  }
};

export default Counter;

三、实现效果

计数器组件包含:

  1. 显示当前数值的标题
  2. "+"、"-" 和 "重置" 三个操作按钮
  3. 当数值 >=10 时显示提示信息
  4. 按钮悬停时的颜色变化效果
  5. 整洁的卡片式布局

四、学习要点总结

  1. 基础概念

    • useState 是用于给函数组件添加状态管理的 Hook
    • 遵循 const [state, setState] = useState(initialValue) 语法
  2. 使用规则

    • 只在组件的顶层调用 Hooks
    • 不要在循环、条件或嵌套函数中调用 Hooks
    • 遵循不可变原则(immutability)
  3. 最佳实践

    • 对于复杂对象,使用扩展运算符进行合并更新
    • 异步操作时使用函数式更新确保获取最新状态
    • 拆分多个 useState 管理不同状态
  4. 性能优化

    • 对于昂贵的初始化,使用函数式初始化
    • 当更新依赖前值时,必须使用函数式更新
    • 使用 React.memo 防止不必要的重新渲染
  5. 常见错误

    • 直接修改状态对象

    JAVASCRIPT

    // 错误示例
    const [user, setUser] = useState({name: 'John'});
    user.name = 'Mike'; // 直接修改原对象
    setUser(user);      // 不会触发更新
    
    // 正确做法
    setUser({...user, name: 'Mike'});
    
  • 在渲染函数中执行副作用操作
  • 忽视异步更新的特性

五、扩展阅读推荐

官方文档

  1. Hooks 简介
  2. useState API 文档
  3. Hooks 常见问题

优质文章

  1. useState 完全指南
  2. Hooks 原理剖析
  3. 函数式更新深入解析
  4. Hooks 最佳实践
  5. Hooks 与类组件对比

推荐学习路径

  1. 掌握 useState → useEffect → useContext 基础三件套
  2. 学习自定义 Hook 实现逻辑复用
  3. 了解 useReducer 管理复杂状态
  4. 学习性能优化相关 Hooks(useMemo/useCallback)
  5. 探索第三方 Hooks 库(如 ahooks)

进阶资源

  1. React Hooks 完全指南(免费电子书)
  2. Hooks 实现原理视频解析
  3. Hooks 测试策略

六、实践步骤

可以以下步骤进行实践:

  1. 从简单计数器开始
  2. 实现表单输入控制
  3. 创建动态列表组件
  4. 开发带有复杂状态的购物车
  5. 尝试将业务逻辑抽象为自定义 Hooks

一、表单输入控制

JSX

import React, { useState } from 'react';

function UserForm() {
  // 使用单个对象管理所有表单字段
  const [formData, setFormData] = useState({
    username: '',
    email: '',
    password: '',
    newsletter: false
  });

  // 统一处理输入变化
  const handleInputChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  // 处理表单提交
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('表单提交数据:', formData);
    alert(JSON.stringify(formData, null, 2));
  };

  return (
    <form style={formStyles} onSubmit={handleSubmit}>
      <div style={inputGroup}>
        <label>用户名:</label>
        <input
          type="text"
          name="username"
          value={formData.username}
          onChange={handleInputChange}
        />
      </div>

      <div style={inputGroup}>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleInputChange}
        />
      </div>

      <div style={inputGroup}>
        <label>密码:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleInputChange}
        />
      </div>

      <div style={checkboxGroup}>
        <label>
          <input
            type="checkbox"
            name="newsletter"
            checked={formData.newsletter}
            onChange={handleInputChange}
          />
          订阅新闻邮件
        </label>
      </div>

      <button type="submit" style={submitButton}>提交</button>
    </form>
  );
}

// 样式配置
const formStyles = {
  maxWidth: '400px',
  margin: '2rem auto',
  padding: '2rem',
  backgroundColor: '#f8f9fa',
  borderRadius: '8px'
};

const inputGroup = {
  marginBottom: '1rem'
};

const checkboxGroup = {
  margin: '1rem 0'
};

const submitButton = {
  backgroundColor: '#28a745',
  color: 'white',
  padding: '0.5rem 1rem',
  border: 'none',
  borderRadius: '4px',
  cursor: 'pointer'
};

export default UserForm;

学习要点:

  1. 使用对象统一管理表单状态
  2. 处理多种输入类型(文本/复选框)
  3. 动态属性名更新技巧([name]: value)
  4. 表单提交时访问最新状态

二、动态列表组件

JSX

import React, { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: '学习React Hooks', completed: false },
    { id: 2, text: '练习useState', completed: true }
  ]);
  const [newTodo, setNewTodo] = useState('');

  // 添加新待办事项
  const addTodo = () => {
    if (newTodo.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: newTodo,
        completed: false
      }]);
      setNewTodo('');
    }
  };

  // 切换完成状态
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  // 删除待办事项
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div style={container}>
      <h2>待办事项列表 ({todos.length})</h2>
      
      <div style={inputGroup}>
        <input
          type="text"
          value={newTodo}
          onChange={(e) => setNewTodo(e.target.value)}
          placeholder="输入新事项"
          style={inputStyle}
        />
        <button onClick={addTodo} style={addButton}>添加</button>
      </div>

      <ul style={listStyle}>
        {todos.map(todo => (
          <li key={todo.id} style={itemStyle(todo.completed)}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span style={{ flex: 1 }}>{todo.text}</span>
            <button 
              onClick={() => deleteTodo(todo.id)}
              style={deleteButton}
            >删除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

// 样式配置
const container = {
  maxWidth: '600px',
  margin: '2rem auto',
  padding: '1rem'
};

const inputGroup = {
  display: 'flex',
  gap: '0.5rem',
  marginBottom: '1rem'
};

const inputStyle = {
  flex: 1,
  padding: '0.5rem'
};

const addButton = {
  backgroundColor: '#17a2b8',
  color: 'white',
  border: 'none',
  padding: '0.5rem 1rem',
  borderRadius: '4px',
  cursor: 'pointer'
};

const listStyle = {
  listStyle: 'none',
  padding: 0
};

const itemStyle = (completed) => ({
  display: 'flex',
  alignItems: 'center',
  padding: '0.5rem',
  margin: '0.5rem 0',
  backgroundColor: completed ? '#d4edda' : '#fff',
  border: '1px solid #ddd',
  borderRadius: '4px',
  opacity: completed ? 0.7 : 1
});

const deleteButton = {
  backgroundColor: '#dc3545',
  color: 'white',
  border: 'none',
  padding: '0.25rem 0.5rem',
  borderRadius: '4px',
  cursor: 'pointer'
};

export default TodoList;

学习要点:

  1. 使用数组管理动态列表
  2. 列表项的增删改操作
  3. 正确使用key属性
  4. 复杂状态对象的更新方法
  5. 条件样式渲染技巧

三、购物车组件(复杂状态)

JSX

import React, { useState } from 'react';

const initialProducts = [
  { id: 1, name: '商品A', price: 100, quantity: 1 },
  { id: 2, name: '商品B', price: 200, quantity: 2 }
];

function ShoppingCart() {
  const [cart, setCart] = useState(initialProducts);
  const [newProduct, setNewProduct] = useState('');

  // 计算总价
  const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);

  // 添加新商品
  const addProduct = () => {
    if (newProduct.trim()) {
      setCart([...cart, {
        id: Date.now(),
        name: newProduct,
        price: Math.floor(Math.random() * 500) + 100,
        quantity: 1
      }]);
      setNewProduct('');
    }
  };

  // 更新商品数量
  const updateQuantity = (id, delta) => {
    setCart(cart.map(item => {
      if (item.id === id) {
        const newQuantity = Math.max(1, item.quantity + delta);
        return { ...item, quantity: newQuantity };
      }
      return item;
    }));
  };

  // 移除商品
  const removeProduct = (id) => {
    setCart(cart.filter(item => item.id !== id));
  };

  return (
    <div style={container}>
      <h2>购物车 (总价: ¥{total})</h2>
      
      <div style={inputGroup}>
        <input
          type="text"
          value={newProduct}
          onChange={(e) => setNewProduct(e.target.value)}
          placeholder="输入商品名称"
          style={inputStyle}
        />
        <button onClick={addProduct} style={addButton}>添加商品</button>
      </div>

      <ul style={listStyle}>
        {cart.map(item => (
          <li key={item.id} style={itemStyle}>
            <div style={itemInfo}>
              <span style={itemName}>{item.name}</span>
              <span>单价: ¥{item.price}</span>
            </div>
            
            <div style={quantityControls}>
              <button 
                onClick={() => updateQuantity(item.id, -1)}
                style={controlButton}
              >-</button>
              <span style={quantityDisplay}>{item.quantity}</span>
              <button 
                onClick={() => updateQuantity(item.id, 1)}
                style={controlButton}
              >+</button>
            </div>

            <div style={itemSubtotal}>
              小计: ¥{item.price * item.quantity}
              <button
                onClick={() => removeProduct(item.id)}
                style={removeButton}
              >删除</button>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
}

// 样式配置
const container = {
  maxWidth: '800px',
  margin: '2rem auto',
  padding: '1rem'
};

const inputGroup = {
  display: 'flex',
  gap: '0.5rem',
  marginBottom: '1rem'
};

const inputStyle = {
  flex: 1,
  padding: '0.5rem'
};

const addButton = {
  backgroundColor: '#007bff',
  color: 'white',
  border: 'none',
  padding: '0.5rem 1rem',
  borderRadius: '4px',
  cursor: 'pointer'
};

const listStyle = {
  listStyle: 'none',
  padding: 0
};

const itemStyle = {
  display: 'flex',
  justifyContent: 'space-between',
  alignItems: 'center',
  padding: '1rem',
  margin: '0.5rem 0',
  backgroundColor: '#fff',
  border: '1px solid #ddd',
  borderRadius: '4px'
};

const itemInfo = {
  flex: 2,
  display: 'flex',
  flexDirection: 'column',
  gap: '0.5rem'
};

const itemName = {
  fontWeight: 'bold'
};

const quantityControls = {
  display: 'flex',
  alignItems: 'center',
  gap: '0.5rem'
};

const controlButton = {
  padding: '0.25rem 0.5rem',
  minWidth: '32px',
  backgroundColor: '#6c757d',
  color: 'white',
  border: 'none',
  borderRadius: '4px',
  cursor: 'pointer'
};

const quantityDisplay = {
  minWidth: '30px',
  textAlign: 'center'
};

const itemSubtotal = {
  flex: 1,
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'flex-end',
  gap: '0.5rem'
};

const removeButton = {
  backgroundColor: '#dc3545',
  color: 'white',
  border: 'none',
  padding: '0.25rem 0.5rem',
  borderRadius: '4px',
  cursor: 'pointer'
};

export default ShoppingCart;

学习要点:

  1. 多层嵌套状态的管理
  2. 复杂状态更新模式
  3. 派生状态(总价)的计算
  4. 不可变数据更新模式
  5. 复杂组件的样式组织

四、自定义Hook:useCart

JSX

// useCart.js
import { useState } from 'react';

function useCart(initialItems = []) {
  const [cart, setCart] = useState(initialItems);

  const total = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);

  const addItem = (newItem) => {
    setCart([...cart, {
      ...newItem,
      id: Date.now(),
      quantity: 1
    }]);
  };

  const updateQuantity = (itemId, delta) => {
    setCart(currentCart =>
      currentCart.map(item =>
        item.id === itemId
          ? { ...item, quantity: Math.max(1, item.quantity + delta) }
          : item
      )
    );
  };

  const removeItem = (itemId) => {
    setCart(currentCart => currentCart.filter(item => item.id !== itemId));
  };

  return {
    cart,
    total,
    addItem,
    updateQuantity,
    removeItem
  };
}

export default useCart;

// 使用示例
function CartComponent() {
  const { cart, total, addItem, updateQuantity, removeItem } = useCart();
  // ...组件实现与前面购物车示例类似
}

学习要点:

  1. 自定义Hook的命名规范(必须用use开头)
  2. 状态逻辑的封装
  3. Hook之间的通信
  4. 返回可操作的方法集
  5. 实现业务逻辑复用

推荐练习项目:

  • 个人博客系统
  • 任务管理系统(类似Trello)
  • 电子商务平台
  • 实时数据监控仪表盘

学完后建议弄清以下问题:

  1. 状态更新的原理是什么?
  2. 如何避免不必要的重新渲染?
  3. 复杂状态如何组织更合理?
  4. 如何调试状态变化?
  5. 如何测试Hook相关逻辑?

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

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

相关文章

芯科科技推出的BG29超小型低功耗蓝牙®无线SoC,是蓝牙应用的理想之选

具有扩大的内存和超低功耗特性的超小型BG29是互联健康设备的理想之选 低功耗无线领域内的领导性创新厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;今日宣布&#xff1a;推出全新的第二代无线开发平台产品BG29系列无线片上系统…

export、export default 和 module.exports 深度解析

文章目录 1. 模块系统概述1.1 模块系统对比1.2 模块加载流程 2. ES Modules2.1 export 使用2.2 export default 使用2.3 混合使用 3. CommonJS3.1 module.exports 使用3.2 exports 使用 4. 对比分析4.1 语法对比4.2 使用场景 5. 互操作性5.1 ES Modules 中使用 CommonJS5.2 Com…

qwen2.5-vl多机多卡分布式部署

记录一下工作中进行多机多卡部署qwen2.5-vl多模态大模型踩过的坑 第一个天坑就是官方提供的镜像qwenllm/qwenvl:2.5-cu121有问题&#xff0c;在titan显卡会抛出cuda error:no kernel image is availabe for execution on the device. 这是cuda内核与GPU不兼容的问题&#xff0c…

【红黑树】—— 我与C++的不解之缘(二十五)

前言 学习了avl树&#xff0c;现在来学习红黑树。 一、什么是红黑树 红黑树是一颗平衡二叉搜索树&#xff0c;它每一个节点增加了一个存储位表示节点的颜色&#xff0c;可以是红色或者黑色。 相比较于AVL树&#xff0c;红黑树也是一个自平衡二叉搜索树&#xff0c;但是它与AVL树…

驾驭 DeepSeek 科技之翼,翱翔现代学习新天际

在当今这个信息爆炸的时代&#xff0c;学习的方式和途径正在经历着前所未有的变革。人工智能技术的飞速发展&#xff0c;为我们的学习带来了全新的机遇和挑战。DeepSeek 作为一款强大的大语言模型&#xff0c;凭借其卓越的性能和丰富的功能&#xff0c;为现代学习注入了新的活力…

DeepSeek本地部署 (Windows+Ollama+Docker Desktop+ RAGFlow)

适用场景&#xff1a; 1、商城的小机器人自动根据实际情况回复 2、需要7*24小时运行在线回复&#xff0c;如&#xff1a;在线购物、在线咨询、在线招生等 3、无人值守环境 2025年1月&#xff0c;DeepSeek 正式发布 DeepSeek-R1 推理大模型&#xff0c;DeepSeek-R1 成本价格低…

SPI驱动(八) -- SPI_DAC设备驱动程序

文章目录 参考资料&#xff1a;一、编写设备树二、 编写驱动程序三、编写测试APP四、Makefile五、上机实验 参考资料&#xff1a; 参考资料&#xff1a; 内核头文件&#xff1a;include\linux\spi\spi.h内核文档&#xff1a;Documentation\spi\spidevDAC芯片手册&#xff1a;…

MySQL 衍生表(Derived Tables)

在SQL的查询语句select …. from …中&#xff0c;跟在from子句后面的通常是一张拥有定义的实体表&#xff0c;而有的时候我们会用子查询来扮演实体表的角色&#xff0c;这个在from子句中的子查询会返回一个结果集&#xff0c;这个结果集可以像普通的实体表一样查询、连接&…

HarmonyOS NEXT开发进阶(十二):build-profile.json5 文件解析

文章目录 一、前言二、Hvigor脚本文件三、任务与任务依赖图四、多模块管理4.1 静态配置模块 五、分模块编译六、配置多目标产物七、配置APP多目标构建产物八、定义 product 中包含的 target九、拓展阅读 一、前言 编译构建工具DevEco Hvigor&#xff08;以下简称Hvigor&#x…

深度学习笔记(37周)

目录 摘要 Abstracts 1. 介绍 2. 相关工作 3. 模型 3.1 时序段网络TSN 3.2 学习时序段网络 4. 训练结果 5. 结论 摘要 本周阅读的论文是《Temporal Segment Networks: Towards Good Practices for Deep Action Recognition》。作者主要想通过较少的训练样本&#xff…

ELK+Filebeat+Kafka+Zookeeper安装部署

1.安装zookeeper zookpeer下载地址:apache-zookeeper-3.7.1-bin.tar.gzhttps://link.csdn.net/?targethttps%3A%2F%2Fwww.apache.org%2Fdyn%2Fcloser.lua%2Fzookeeper%2Fzookeeper-3.7.1%2Fapache-zookeeper-3.7.1-bin.tar.gz%3Flogin%3Dfrom_csdn 1.1解压安装zookeeper软件…

【软考-架构】3.3、模式分解-事务并发-封锁协议

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 模式分解&#xff08;难点&#xff09;无损分解&#x1f4af;考试真题并发控制封锁协议&#x1f4af;考试真题第一题第二题 模式分解&#xff08;难点&#xff09; 保持函…

审批工作流系统xFlow

WorkFlow-审批流程系统 该项目为完全开源免费项目 可用于学习或搭建初始化审批流程系统 希望有用的小伙伴记得点个免费的star gitee仓库地址 仿钉钉飞书工作审批流系统 介绍 前端技术栈: vue3 ts vite arcodesign eslint 后端技术栈:springbootspring mvc mybatis mavenmysq…

【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]

hello&#xff0c;好久不见&#xff01; 云边有个稻草人-CSDN博客 上篇内容&#xff0c;回顾一下吧【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解代码解析]-CSDN博客 今天我们来学习下篇 目录 &#xff08;2&#xff09;快速排序 【挖坑法】 —思路 —思路…

定制开发开源 AI 智能名片 S2B2C 商城小程序源码在小程序直播营销中的应用与价值

摘要&#xff1a; 本文主要探讨了定制开发开源 AI 智能名片 S2B2C 商城小程序源码在小程序直播营销中的应用与价值。首先详细阐述了小程序直播的基本概念、特点、发展历程及营销意义&#xff0c;包括其便捷性、广泛的受众连接能力以及对企业推广的重要作用。接着深入剖析了定制…

蓝桥杯Python赛道备赛——Day3:排序算法(二)(归并排序、堆排序、桶排序)

本博客是蓝桥杯备赛系列中排序算法的第二期&#xff0c;包括&#xff1a;归并排序、堆排序和桶排序。每一个算法都在给出概念解释的同时&#xff0c;给出了示例代码&#xff0c;以供低年级师弟师妹们学习和练习。 由于本期的三个算法的复杂度相对来说要高于上一期的三个算法&am…

Type-C:智能家居的电力革命与空间美学重构

在万物互联的时代浪潮中&#xff0c;家居空间正经历着从功能容器到智慧终端的蜕变。当意大利设计师安东尼奥奇特里奥提出"消失的设计"理念二十年后&#xff0c;Type-C充电技术正以润物无声的方式重塑着现代家居的形态与内核&#xff0c;开启了一场静默的居住革命。 【…

第十五届蓝桥杯C/C++组:宝石组合题目(从小学奥数到编程题详解)

这道题目真的一看就不好做&#xff0c;如果直接暴力去做百分之90必挂掉&#xff0c;那么这道题目到底应该怎么去做呢&#xff1f;这我们就得从小学奥数开始聊了。&#xff08;闲话&#xff1a;自从开始蓝桥杯备赛后&#xff0c;每天都在被小学奥数震惊&#xff0c;为什么我小的…

ECharts中Map(地图)样式配置、渐变色生成

前言 ECharts是我们常用的图表控件&#xff0c;功能特别强大&#xff0c;每次使用都要查API比较繁琐&#xff0c;这里就记录开发中常用的配置。 官网&#xff1a;https://echarts.apache.org/handbook/zh/get-started 配置项&#xff1a;https://echarts.apache.org/zh/opti…

MySQL | MySQL表的增删改查(CRUD)

目录 前言&#xff1a;什么是 CRUD ?一、Creat 新增1.1 语法1.2 示例1.2.1 单行数据全列插入1.2.2 单行数据指定列插入1.2.3 多行数据指定列插入 二、Retrieve 检索2.1 语法2.2 示例2.2.1 全列查询2.2.2 指定列查询2.2.3 查询字段为表达式2.2.4 结果去重查询2.2.5 where条件查…