React 从入门到出门第二章 生命周期函数与内置 Hooks 整体认知

大家好~ 上一篇我们聊了 React 19 的 JSX 增强特性和函数组件基础,今天咱们聚焦另一个核心知识点------生命周期函数与内置 Hooks。

很多刚接触 React 的同学会有个误区:"只有 class 组件才有生命周期"。其实在 React 19 中,函数组件通过 Hooks 完全可以实现甚至优化生命周期的逻辑,而且 Hooks 是函数组件的核心能力,所有 React 19 新特性都围绕 Hooks 展开。

今天这篇文章,我们就从"生命周期的本质是什么"入手,先搞懂 React 组件的核心运行流程,再逐一认识 React 19 中 8 个常用内置 Hooks(useState、useEffect、useContext、useCallback、useRef、useMemo、useDeferredValue、useTransition),结合代码示例讲清"核心作用+应用场景+使用注意",最后用精准的图例梳理清楚 Hooks 与生命周期的对应关系,帮大家建立完整的知识框架。

一、先搞懂:生命周期的本质是"组件的运行阶段"

不管是 class 组件还是函数组件,React 组件的核心运行流程都可以分为三个阶段:挂载阶段(组件第一次渲染到页面)、更新阶段(组件数据变化重新渲染)、卸载阶段(组件从页面中移除)

生命周期函数,就是 React 提供的、允许我们在组件不同运行阶段插入自定义逻辑的"钩子"。比如:

  • 挂载阶段:我们可能需要请求初始化数据、绑定事件监听;
  • 更新阶段:我们可能需要根据数据变化更新 DOM 、做性能优化;
  • 卸载阶段:我们可能需要清除定时器、取消事件监听,避免内存泄漏。

React 19 中生命周期的实现方式

在 React 早期,class 组件通过 componentDidMountcomponentDidUpdatecomponentWillUnmount 等生命周期方法实现上述逻辑。但在 React 19 中,函数组件+ Hooks 已经成为主流,官方也更推荐这种方式------因为 Hooks 能让逻辑复用更简单,代码更简洁。

下面先通过一个精准的图例,直观看看 React 19 组件的完整生命周期流程,以及函数组件中对应的 Hooks 从图中可以看出:useEffect 是最核心的"生命周期 Hooks",能覆盖挂载、更新、卸载三个阶段的逻辑;而 useState、useContext 等 Hooks 则聚焦于状态管理或性能优化,为生命周期中的逻辑提供支撑。

二、React 19 8 个核心内置 Hooks 详解(核心作用+应用场景+代码示例)

React 19 提供了一系列内置 Hooks,每个 Hooks 都有明确的使用场景,遵循"命名以 use 开头、只能在函数组件顶层调用"的规则。下面我们逐一讲解 8 个常用核心 Hooks,重点突出应用场景,结合实战代码说明用法。

1. useState:组件状态管理的"基石"

核心作用:为函数组件添加"可变化的状态"(组件内部可修改、修改后触发重新渲染的数据),是实现组件更新生命周期的基础。

应用场景

  • 管理组件内部的简单状态(如计数器数值、表单输入值、弹窗显示/隐藏状态);
  • 存储组件渲染所需的动态数据(如列表数据、用户信息等,可配合 useEffect 请求后更新);
  • 实现组件内部的状态联动(如根据一个状态变化同步更新另一个状态)。

语法const [状态变量, 状态更新函数] = useState(初始值);

使用注意 :状态更新是异步的,若需基于前一个状态更新,需使用函数式更新(setCount(prev => prev + 1));更新对象/数组时需遵循"不可变原则",不能直接修改原数据。

实战案例:表单输入与弹窗控制

ini 复制代码
import { useState } from 'react';

function FormWithModal() {
  // 场景1:管理表单输入状态(用户名、密码)
  const [formData, setFormData] = useState({ username: '', password: '' });
  // 场景2:管理弹窗显示/隐藏状态
  const [isModalOpen, setIsModalOpen] = useState(false);

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    // 不可变更新对象状态
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    // 表单验证通过后打开弹窗
    if (formData.username && formData.password) {
      setIsModalOpen(true);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          name="username"
          value={formData.username}
          onChange={handleInputChange}
          placeholder="请输入用户名"
        />
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleInputChange}
          placeholder="请输入密码"
        />
        <button type="submit">提交</button>
      </form>

      {/* 弹窗组件,根据 isModalOpen 状态显示/隐藏 */}
      {isModalOpen && (
        <div style={{ position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', border: '1px solid #ccc', padding: '20px' }}>
          <h3>提交成功!</h3>
          <p>用户名:{formData.username}</p>
          <button onClick={() => setIsModalOpen(false)}>关闭</button>
        </div>
      )}
    </div>
  );
}

2. useEffect:处理副作用的"万能 Hooks"

核心作用 :处理组件的"副作用"(即不直接参与 UI 渲染的逻辑,如数据请求、事件绑定、定时器、清理资源等),覆盖 class 组件 componentDidMountcomponentDidUpdatecomponentWillUnmount 三个生命周期方法的功能。

应用场景

  • 挂载阶段:初始化数据请求(如页面加载时请求列表数据)、绑定全局事件(如窗口大小监听、滚动监听);
  • 更新阶段:依赖数据变化后重新请求数据(如根据用户 ID 变化请求对应用户详情)、根据状态变化更新 DOM 样式;
  • 卸载阶段:清理资源(如清除定时器、取消事件监听、取消未完成的请求),避免内存泄漏。

语法useEffect(() => { 副作用逻辑; return () => { 清理逻辑; }; }, [依赖数组]);

使用注意 :依赖数组需包含副作用逻辑中使用的所有状态/变量,避免遗漏导致使用旧值;空依赖数组([])仅在挂载时执行一次,无数组则每次渲染都执行。

实战案例:数据请求+事件监听+定时器清理

javascript 复制代码
import { useEffect, useState } from 'react';

function DataFetchWithCleanup() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 场景1:挂载时请求数据
    const fetchData = async () => {
      try {
        const res = await fetch('https://api.example.com/list');
        const result = await res.json();
        setData(result);
      } catch (err) {
        console.error('请求失败:', err);
      } finally {
        setLoading(false);
      }
    };
    fetchData();

    // 场景2:绑定窗口滚动监听事件
    const handleScroll = () => {
      console.log('滚动位置:', window.scrollY);
    };
    window.addEventListener('scroll', handleScroll);

    // 场景3:开启定时器
    const timer = setInterval(() => {
      console.log('定时器执行中...');
    }, 1000);

    // 清理逻辑:卸载时执行
    return () => {
      window.removeEventListener('scroll', handleScroll); // 移除事件监听
      clearInterval(timer); // 清除定时器
      // 若有未完成的请求,可在此处取消(如使用 AbortController)
    };
  }, []); // 空依赖,仅挂载时执行

  if (loading) return <div>加载中...</div>;

  return (
    <ul>
      {data.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

3. useContext:跨组件状态共享的"快捷方式"

核心作用:解决"组件层级过深时的 props 透传问题"(即"props drilling"),允许子组件直接获取父组件提供的共享状态,无需通过中间组件层层传递。

应用场景

  • 共享全局基础状态(如主题色、语言设置、用户登录状态);
  • 共享组件树内的公共状态(如表单步骤组件间的步骤状态、列表页与详情页的共享筛选条件);
  • 简化跨层级组件的通信(如爷爷组件向孙子组件传递数据,无需父组件中转)。

使用步骤

  1. 创建 Context:const MyContext = createContext(默认值);(默认值仅在无 Provider 时生效);
  2. 提供 Context:用 <MyContext.Provider value={共享数据/方法}> 包裹需要共享数据的组件树;
  3. 消费 Context:在子组件中用 useContext(MyContext) 获取共享数据。

使用注意:useContext 适合共享"变化不频繁"的状态,若需频繁更新且涉及复杂逻辑,建议结合 useReducer 或专门的状态管理库(如 Redux Toolkit)。

实战案例:全局主题切换(多组件共享主题状态)

javascript 复制代码
import { createContext, useContext, useState } from 'react';

// 1. 创建主题 Context
const ThemeContext = createContext('light');

// 2. 提供 Context 的顶层组件(如 App 或专门的 Provider 组件)
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  // 共享的方法:切换主题
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };

  // 向子组件提供的共享数据(状态+方法)
  const contextValue = { theme, toggleTheme };

  return (
    <ThemeContext.Provider value={contextValue}>
      {children} {/* 包裹需要共享主题的所有组件 */}
    </ThemeContext.Provider>
  );
}

// 3. 消费 Context 的子组件1:主题按钮(任意层级)
function ThemeToggleButton() {
  const { theme, toggleTheme } = useContext(ThemeContext);
  return (
    <button
      onClick={toggleTheme}
      style={{
        background: theme === 'light' ? '#fff' : '#333',
        color: theme === 'light' ? '#333' : '#fff',
        padding: '8px 16px',
        border: '1px solid #ccc'
      }}
    >
      切换到 {theme === 'light' ? '深色' : '浅色'} 主题
    </button>
  );
}

// 4. 消费 Context 的子组件2:主题内容区(任意层级)
function ThemeContent() {
  const { theme } = useContext(ThemeContext);
  return (
    <div
      style={{
        width: '300px',
        height: '200px',
        margin: '20px 0',
        background: theme === 'light' ? '#fff' : '#333',
        color: theme === 'light' ? '#333' : '#fff',
        padding: '20px'
      }}
    >
      <h3>当前主题:{theme}</h3>
      <p>跨组件共享主题状态示例</p>
    </div>
  );
}

// 根组件
function App() {
  return (
    <ThemeProvider>
      <div>
        <ThemeToggleButton />
        <ThemeContent />
      </div>
    </ThemeProvider>
  );
}

4. useCallback:缓存函数的"性能优化工具"

核心作用:缓存函数引用,避免函数在组件每次渲染时重新创建,减少因函数引用变化导致的子组件不必要重渲染。

应用场景

  • 向子组件传递回调函数时(尤其是子组件使用 React.memo 包裹进行性能优化时);
  • 函数作为 useEffect 的依赖时(避免因函数重新创建导致 useEffect 不必要执行);
  • 高频渲染的组件中(如列表项组件,每个列表项需传递点击事件函数)。

语法const 缓存的函数 = useCallback(原函数, [依赖数组]);

使用注意 :依赖数组需包含原函数中使用的所有外部变量/状态;若函数无依赖,依赖数组可为空([]);仅在函数引用变化会导致性能问题时使用,无需过度使用。

实战案例:优化子组件重渲染

javascript 复制代码
import { useState, useCallback, memo } from 'react';

// 子组件:用 React.memo 包裹,仅在 props 变化时重渲染
const Child = memo(({ onClick, name }) => {
  console.log(`${name} 子组件渲染了`);
  return (
    <button onClick={onClick} style={{ margin: '5px' }}>
      {name} 按钮
    </button>
  );
});

function UseCallbackDemo() {
  const [count, setCount] = useState(0);

  // 未使用 useCallback:每次渲染都会重新创建函数,导致 Child 重渲染
  const handleNormalClick = () => {
    console.log('普通按钮点击');
  };

  // 使用 useCallback:缓存函数引用,仅依赖变化时才重新创建
  const handleCachedClick = useCallback(() => {
    console.log('缓存按钮点击');
  }, []); // 无依赖,永久缓存

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => setCount(prev => prev + 1)}>+1(触发父组件渲染)</button>
      <Child onClick={handleNormalClick} name="普通" />
      <Child onClick={handleCachedClick} name="缓存" />
    </div>
  );
}

运行结果:点击"+1"按钮触发父组件渲染时,"普通按钮"子组件会重新渲染(因 handleNormalClick 函数重新创建),而"缓存按钮"子组件不会重新渲染(因 handleCachedClick 引用未变)。

5. useRef:获取 DOM/保存持久值的"工具 Hooks"

核心作用:有两个核心用途------一是获取 DOM 元素或组件实例;二是保存"持久化值"(组件重新渲染时值不重置,且修改值不会触发组件重新渲染)。

应用场景

  • 获取 DOM 元素:实现输入框自动聚焦、获取 DOM 尺寸/位置、操作 DOM 元素(如设置样式、触发事件);
  • 保存持久值:记录组件渲染次数、保存定时器 ID、保存前一次的状态/Props 值、存储不希望触发重新渲染的数据。

语法const ref 对象 = useRef(初始值);(通过 ref.current 访问/修改值)

使用注意 :修改 ref.current 是同步的,但不会触发组件重新渲染;若需基于 ref 值更新 UI,需配合 useState 或 useEffect。

实战案例:输入框自动聚焦+记录渲染次数

javascript 复制代码
import { useRef, useState, useEffect } from 'react';

function UseRefDemo() {
  const [count, setCount] = useState(0);
  // 场景1:获取 DOM 元素(输入框)
  const inputRef = useRef(null);
  // 场景2:保存持久值(渲染次数)
  const renderCountRef = useRef(0);

  // 每次渲染后更新渲染次数(useEffect 无依赖,每次渲染都执行)
  useEffect(() => {
    renderCountRef.current += 1;
    console.log('组件渲染次数:', renderCountRef.current);
  });

  // 挂载时让输入框自动聚焦
  useEffect(() => {
    inputRef.current.focus();
  }, []);

  // 点击按钮滚动到输入框位置
  const scrollToInput = () => {
    inputRef.current.scrollIntoView({ behavior: 'smooth' });
  };

  return (
    <div style={{ marginTop: '50px' }}>
      <p>计数:{count}</p>
      <p>组件渲染次数:{renderCountRef.current}</p>
      <button onClick={() => setCount(prev => prev + 1)}>+1(触发渲染)</button>
      <button onClick={scrollToInput}>滚动到输入框</button>

      {/* 输入框:通过 ref 关联 */}
      <div style={{ marginTop: '200px' }}>
        <input
          ref={inputRef}
          type="text"
          placeholder="我会自动聚焦..."
          style={{ width: '300px', height: '30px' }}
        />
      </div>
    </div>
  );
}

6. useMemo:缓存计算结果的"性能优化工具"

核心作用:缓存"昂贵计算"的结果,避免组件每次渲染时重复执行相同的复杂计算,提升组件渲染性能。

应用场景

  • 执行复杂计算时(如大数据量列表排序、过滤、复杂数学计算);
  • 计算结果作为 props 传递给子组件时(避免因计算结果重新创建导致子组件不必要重渲染);
  • 基于多个状态/Props 推导衍生数据时(如根据筛选条件和排序规则推导过滤后的列表)。

语法const 缓存的计算结果 = useMemo(() => 计算逻辑, [依赖数组]);

使用注意:依赖数组需包含计算逻辑中使用的所有外部变量/状态;仅用于"昂贵计算",简单计算无需使用(缓存本身有轻微开销);useMemo 是"备忘录",仅在依赖变化时重新计算。

实战案例:优化大数据量排序

javascript 复制代码
import { useState, useMemo } from 'react';

function UseMemoDemo() {
  const [list, setList] = useState(() => {
    // 模拟大数据量(10000 条数据)
    return Array.from({ length: 10000 }, (_, i) => ({ id: i, value: Math.random() * 1000 }));
  });
  const [sortType, setSortType] = useState('asc'); // asc:升序,desc:降序

  // 场景:复杂计算(大数据量排序),用 useMemo 缓存结果
  const sortedList = useMemo(() => {
    console.log('执行排序计算...');
    // 模拟昂贵计算(排序 10000 条数据)
    return [...list].sort((a, b) => {
      return sortType === 'asc' ? a.value - b.value : b.value - a.value;
    });
  }, [list, sortType]); // 仅 list 或 sortType 变化时重新排序

  return (
    <div>
      <button onClick={() => setSortType(prev => prev === 'asc' ? 'desc' : 'asc')}>
        切换排序(当前:{sortType === 'asc' ? '升序' : '降序'})
      </button>
      <div style={{ marginTop: '20px' }}>
        {/* 仅渲染前 10 条数据,避免页面卡顿 */}
        {sortedList.slice(0, 10).map(item => (
          <p key={item.id}>ID:{item.id},值:{item.value.toFixed(2)}</p>
        ))}
      </div>
    </div>
  );
}

运行结果:首次渲染和切换排序时会执行排序计算(控制台打印"执行排序计算..."),若仅触发其他不相关状态更新(如添加一个无关计数器),sortedList 会直接使用缓存结果,不会重新排序。

7. useDeferredValue:延迟更新非紧急状态的"体验优化工具"

核心作用:创建一个"延迟版本"的状态,当组件有紧急更新(如输入框输入)时,优先执行紧急更新,非紧急更新延迟到紧急更新完成后再执行,避免页面卡顿,提升用户体验。

应用场景

  • 输入框实时搜索(输入是紧急更新,搜索结果渲染是非紧急更新,避免输入卡顿);
  • 大数据量列表实时筛选(输入筛选条件是紧急更新,筛选结果渲染是非紧急更新);
  • 任何需要"优先响应用户操作"的场景(如拖拽时的非紧急状态更新)。

语法const 延迟状态 = useDeferredValue(原始状态);

使用注意:useDeferredValue 是"被动延迟",依赖原始状态变化;延迟状态会"追平"原始状态,最终与原始状态一致;无需手动清理,React 会自动处理。

实战案例:输入框实时搜索(优化输入体验)

ini 复制代码
import { useState, useDeferredValue } from 'react';

// 模拟大数据量列表(10000 条数据)
const mockList = Array.from({ length: 10000 }, (_, i) => ({
  id: i,
  name: `商品 ${i + 1} - ${Math.random().toString(36).substring(2, 6)}`
}));

function DeferredValueSearch() {
  // 紧急状态:输入框输入值(优先响应)
  const [searchValue, setSearchValue] = useState('');
  // 延迟状态:搜索值的延迟版本(非紧急,等输入完成后再更新)
  const deferredSearchValue = useDeferredValue(searchValue);

  // 根据延迟搜索值筛选列表(非紧急操作)
  const filteredList = mockList.filter(item => {
    return item.name.includes(deferredSearchValue);
  });

  return (
    <div>
      <input
        type="text"
        value={searchValue}
        onChange={(e) => setSearchValue(e.target.value)}
        placeholder="输入关键词搜索商品..."
        style={{ width: '300px', height: '30px', padding: '0 8px' }}
      />
      <div style={{ marginTop: '20px' }}>
        {filteredList.slice(0, 10).map(item => (
          <p key={item.id}>{item.name}</p>
        ))}
        {filteredList.length === 0 && <p>无匹配商品</p>}
      </div>
    </div>
  );
}

效果说明:若不使用 useDeferredValue,输入时会实时执行筛选逻辑(10000 条数据过滤),导致输入框卡顿;使用后,输入操作优先执行,筛选逻辑延迟到输入间隙执行,输入框流畅无卡顿。

8. useTransition:标记非紧急更新的"体验优化工具"

核心作用:将"非紧急的状态更新"标记为过渡更新,React 会优先处理紧急更新(如输入、点击等用户交互),非紧急更新在后台异步执行,避免阻塞用户操作,提升体验。

应用场景

  • 点击按钮触发的大数据量筛选/排序(点击是紧急操作,筛选/排序是非紧急更新);
  • 表单提交后的数据处理(提交操作是紧急的,后续数据加工是非紧急的);
  • 页面切换时的非紧急数据预加载(页面切换是紧急的,预加载数据是非紧急的)。

语法const [isPending, startTransition] = useTransition();

关键说明:

  • startTransition:包裹非紧急的状态更新逻辑;
  • isPending:布尔值,标记过渡更新是否正在进行(可用于显示加载状态)。

使用注意:useTransition 是"主动标记"非紧急更新,需手动将更新逻辑放入 startTransition 中;过渡更新可被中断(如用户触发新的紧急更新),避免无效计算。

实战案例:按钮触发的大数据量排序(优化点击体验)

ini 复制代码
import { useState, useTransition } from 'react';

// 模拟大数据量(10000 条数据)
const mockList = Array.from({ length: 10000 }, (_, i) => ({
  id: i,
  value: Math.random() * 1000
}));

function TransitionSort() {
  const [list, setList] = useState(mockList);
  const [sortType, setSortType] = useState('asc');
  // 获取过渡更新状态(是否正在排序)和标记函数
  const [isPending, startTransition] = useTransition();

  const handleSort = () => {
    const newSortType = sortType === 'asc' ? 'desc' : 'asc';
    setSortType(newSortType); // 紧急更新:切换排序类型文字

    // 非紧急更新:大数据量排序,标记为过渡更新
    startTransition(() => {
      const sortedList = [...mockList].sort((a, b) => {
        return newSortType === 'asc' ? a.value - b.value : b.value - a.value;
      });
      setList(sortedList);
    });
  };

  return (
    <div>
      <button onClick={handleSort} disabled={isPending}>
        {isPending ? '排序中...' : `切换排序(当前:${sortType === 'asc' ? '升序' : '降序'})`}
      </button>
      <div style={{ marginTop: '20px' }}>
        {list.slice(0, 10).map(item => (
          <p key={item.id}>ID:{item.id},值:{item.value.toFixed(2)}</p>
        ))}
      </div>
    </div>
  );
}

效果说明:点击按钮后,排序类型文字(sortType)立即更新(紧急更新),排序逻辑在后台异步执行;排序过程中按钮显示"排序中..."并禁用,避免重复点击;若排序未完成时触发新的紧急操作,排序可被中断,提升整体体验。

三、React 19 生命周期与 Hooks 对应关系梳理(精准图例+核心总结)

为了让大家更清晰地对应"生命周期阶段"与" Hooks 用法",我们用以下精准图例总结,覆盖所有核心场景:

核心总结

  1. 生命周期是"阶段",Hooks 是"实现工具" :函数组件通过不同 Hooks 覆盖挂载、更新、卸载全阶段逻辑,其中 useEffect 是核心生命周期 Hooks,其他 Hooks 按需补充功能;
  2. 8 个核心 Hooks 各司其职:状态管理(useState)、副作用处理(useEffect)、跨组件共享(useContext)、性能优化(useCallback、useMemo)、DOM/持久值(useRef)、体验优化(useDeferredValue、useTransition);
  3. 使用 Hooks 需遵循核心规则:仅在函数组件/自定义 Hooks 顶层调用,不能在条件/循环/嵌套函数中使用;命名以 use 开头;依赖数组需完整包含外部依赖;
  4. 优化类 Hooks 避免过度使用:useCallback、useMemo、useDeferredValue、useTransition 均为优化手段,需结合实际场景使用,简单场景无需额外优化(优化本身有开销)。

四、常见误区与避坑指南

  • 误区 1:过度依赖 useEffect:简单的状态计算、DOM 操作若可同步执行,无需放入 useEffect,避免不必要的渲染延迟;
  • 误区 2:useCallback/useMemo 滥用:简单函数、简单计算无需缓存,仅在确有性能问题时使用;
  • 误区 3:useDeferredValue 与 useTransition 混淆:useDeferredValue 是"被动延迟状态",依赖原始状态;useTransition 是"主动标记更新",需手动包裹更新逻辑;
  • 误区 4:useContext 替代状态管理库:useContext 适合共享少量固定状态,复杂状态更新(如多组件修改同一状态)建议结合 useReducer 或 Redux Toolkit;
  • 误区 5:修改 ref.current 期望触发渲染:ref.current 变化不会触发组件重新渲染,若需更新 UI,需配合 useState 或 useEffect。

五、下一步学习方向

今天我们建立了 React 19 生命周期与 8 个核心 Hooks 的完整认知,这是函数组件开发的核心基础。下一步可以重点学习:

  • 自定义 Hooks:将复用逻辑封装为自定义 Hooks(如 useFetch、useTimer),提升代码复用性;
  • useReducer:处理复杂状态逻辑,替代 useState 实现多状态联动;
  • React 19 新增 Hooks:如 use()、useOptimistic 等,简化异步数据处理和乐观更新;
  • Hooks 性能优化实战:结合 React DevTools 分析组件渲染,精准使用优化类 Hooks。

如果这篇文章对你有帮助,欢迎点赞、收藏、转发~ 有任何问题也可以在评论区留言交流~ 我们下期再见!

相关推荐
脩衜者4 分钟前
极其灵活且敏捷的WPF组态控件ConPipe 2026
前端·物联网·ui·wpf
Mike_jia9 分钟前
Dockge:轻量开源的 Docker 编排革命,让容器管理回归优雅
前端
GISer_Jing15 分钟前
前端GEO优化:AI时代的SEO新战场
前端·人工智能
没想好d18 分钟前
通用管理后台组件库-4-消息组件开发
前端
文艺理科生19 分钟前
Google A2UI 解读:当 AI 不再只是陪聊,而是开始画界面
前端·vue.js·人工智能
晴栀ay21 分钟前
React性能优化三剑客:useMemo、memo与useCallback
前端·javascript·react.js
JS_GGbond22 分钟前
JavaScript继承大冒险:从“原型江湖”到“class殿堂”
前端
XiaoYu200222 分钟前
第6章 Postgres数据库安装
前端·postgresql
洛卡卡了23 分钟前
从活动编排到积分系统:事件驱动在业务系统中的一次延伸
前端·后端·面试
知其然亦知其所以然24 分钟前
别再死记硬背了,一篇文章搞懂 JS 乘性操作符
前端·javascript·程序员