知行札记
专题技术实践Web 界面

DOM、CSS 与 React 渲染

解释结构、布局、级联、状态快照、提交、水合和服务器客户端边界。

浏览器怎样把内容变成界面

HTML 描述结构与语义,DOM 提供可操作对象。CSS 计算样式,布局确定几何位置,绘制与合成形成像素。JavaScript 可以改变结构和样式,随后触发必要更新。读取几何后马上写样式、再读取几何,可能使浏览器反复完成同步布局;诊断需要测实际页面的关键路径。

原生元素提供键盘、表单和辅助技术语义。按钮用于动作,链接用于导航,标签关联输入;自绘元素需要补齐其实际交互。视觉相同的 div 并不自动成为可操作按钮。

CSS 级联综合来源、重要性、层、选择器权重等规则。@layer 帮助安排不同来源的优先关系,CSS 变量保存可消费值,媒体和容器查询按相应条件变化。主题令牌集中表达颜色、排版与间距,组件消费语义角色,可以减少多个位置分别改值的维护。

CSS Modules 组织局部类名;工具类组织约定值;运行或编译时 CSS-in-JS 组织 JS 中的样式表达;Shadow DOM 提供更明确的树内样式边界。选择时比较作用域、动态需求、构建、SSR 和实际成本。归档知识地图的技术“淘汰”谱系属于作者假说,本页不把它变成全生态历史定律。

下面用原生 CSS 展示来源层次和语义令牌。普通声明的层顺序在一处确定;未分层普通样式、!important、来源和权重仍有各自规则,不能只看书写先后。

@layer reset, tokens, components, utilities;

@layer tokens {
  :root {
    --surface: #fff;
    --text: #18202a;
    --accent: #1457c5;
    --space-2: .5rem;
  }
  @media (prefers-color-scheme: dark) {
    :root { --surface: #18202a; --text: #edf1f7; }
  }
}
@layer components {
  .action {
    padding: var(--space-2);
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--accent);
  }
  .action:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
}

Vite SPA 的入口从 index.html 的模块脚本接到 src/main.tsx,后者建立 React root。开发代理可让浏览器请求 /api,由开发服务器转发到服务;生产必须另外部署对应反向代理或配置真实 API origin:

vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: { proxy: { '/api': 'http://127.0.0.1:3000' } },
});
src/main.tsx
import { createRoot } from 'react-dom/client';
import './styles.css';
import { App } from './App';

const container = document.getElementById('root');
if (!container) throw new Error('Missing root container');
createRoot(container).render(<App />);

App 是应用组件出口,HTML 中需有 id="root" 和加载该模块的 script。项目脚本分别运行 vite、tsc --noEmit、vite build;开发启动不能代替检查。以上说明了接线,未执行新的 Vite 项目。Vite 入门

React 在何处计算与改变

状态更新请求一次渲染。组件函数用当次 props 和 state 计算输出,React 在提交中更新宿主界面。函数可能多次执行或一次结果被放弃,因此渲染应保持纯计算。事件处理器发起用户动作,Effect 连接渲染后的外部系统。React 渲染与提交

状态是当次渲染的快照。连续更新依赖旧值时,可以传更新函数;把网络结果复制到多个本地状态,会增加同步责任。列表 key 表达同级元素的身份,索引在插入、删除和重排时可能把原状态接到另一个对象。

const [count, setCount] = useState(0);
function addTwo() {
  setCount(current => current + 1);
  setCount(current => current + 1);
}

此教学片段表达更新队列中的计算关系,不提供完整组件。记忆化减少某些重复计算或传播,前提是依赖与身份稳定;性能需要实际测量,不能以所有位置加 useMemo 为目标。

外部资源怎样跟随界面生命周期

Effect 建立订阅、连接或第三方实例,清理解除对应资源。依赖改变时,旧关系清理后建立新关系;卸载也需要清理。开发 Strict Mode 的额外检查能暴露缺失清理,生产次数按实际框架行为判断。React Effect

只根据已有状态计算一个值,可以直接派生。发起购买等明确用户动作应由事件入口组织,避免 Effect 随渲染重新产生外部效果。读数、播放和网络仍要处理异步拒绝及过期结果。

HTML、代码与水合各承担什么

CSR 在浏览器建立初始界面;SSR 在请求期间取得 HTML;SSG 在构建阶段生成 HTML;增量或缓存策略决定何时更新。取得 HTML 能减少等待可见内容的工作,交互代码、数据和水合仍可能产生成本。

水合把客户端行为接到已有服务器 HTML,要求双方初始结构能够匹配。当前时间、随机值、浏览器独有条件或语言差异可能破坏这一关系,应建立稳定初始输入或明确采用客户端更新。React hydrateRoot

React Server Components 决定哪些组件在服务器执行及怎样传递结果;它与生成 HTML 的时间策略是不同维度。use client 标记客户端模块边界,该边界中的代码仍可能参与服务器预渲染,不能据名称假定只在浏览器执行。服务器秘密和只适合服务器的依赖需要受控边界。

最后更新于

本页目录