拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零搭建 Todo App:Vite + React + TypeScript 脚手架与 Oxlint 工程化实践

从零搭建 Todo App:Vite + React + TypeScript 脚手架与 Oxlint 工程化实践
  • 前端
  • 教程
  • 文档

【免费下载链接】reactjs-interview-questions

List of top 500 ReactJS Interview Questions & Answers....Coding exercise questions are coming soon!!

项目地址:https://gitcode.com/GitHub_Trending/re/reactjs-interview-questions
点击查看免费下载

本文以 coding-projects/todo-app/README.md 为骨架,系统讲解该 Todo 应用基于 Vite + React + TypeScript 模板的工程化配置:热更新(HMR)与官方插件选型、React Compiler 的取舍、Oxlint 类型感知 lint 规则的扩展,并结合仓库内完整的增删改查源码,展示这套工具链在真实 CRUD 应用中的落地方式。读完你将掌握该模板的每一处配置含义,并能在自己的项目中复刻同样的脚手架与代码组织。

一、模板定位:最小化 React + Vite 工程,开箱即用

coding-projects/todo-app是一个基于官方React + TypeScript + Vite模板搭建的最小化前端工程。模板的目标是“以最少的配置让 React 跑在 Vite 上,并自带热更新(HMR)与 Oxlint 检查规则”,因此它的 package.json 非常精简:

{ "name": "todo-app", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "oxlint", "preview": "vite preview" }, "dependencies": { "react": "^19.2.8", "react-dom": "^19.2.8" }, "devDependencies": { "@vitejs/plugin-react": "^6.0.4", "oxlint": "^1.75.0", "typescript": "~6.0.2", "vite": "^8.2.0" } }

四个脚本对应完整的开发闭环:

脚本命令作用
devvite启动开发服务器,内置 HMR,代码改动即时热更新
buildtsc -b && vite build先用tsc -b对项目做类型检查与增量构建,再交给 Vite 产出生产 bundle
lintoxlint运行 Oxlint 进行静态检查(默认读取.oxlintrc.json或内置默认规则)
previewvite preview本地预览生产构建产物,验证 build 结果

从依赖可见,该工程刻意保持“零 UI 框架、零路由、零状态管理库”的最小形态,业务侧仅依赖 React 19 与 React DOM,符合模板“minimal setup”的定位。源码入口 src/main.tsx 也印证了这一点——通过createRoot挂载,并包裹<StrictMode>以在开发期暴露副作用问题:

createRoot(document.getElementById('root')!).render( <StrictMode> <App /> </StrictMode>, )

对应的宿主页面 index.html 只提供一个<div id="root">挂载点,并以<script type="module" src="/src/main.tsx">引入应用入口,这正是 Vite 约定式入口的标准用法。

二、HMR 与两个官方插件:plugin-react(Oxc)与 plugin-react-swc(SWC)

模板文档明确说明:目前官方提供两个 React 插件,均可接入 Vite 以获得 React 快速刷新(Fast Refresh)与 JSX 转换支持:

  • @vitejs/plugin-react:基于 Oxc 编译器(Rust 编写的高性能 JS/TS 工具链)实现 JSX 转换与 HMR;
  • @vitejs/plugin-react-swc:基于 SWC(Rust 编写的编译平台)实现同样的能力,适合希望用 SWC 统一编译与转译管线的项目。

在本仓库中,todo-app 实际选用的是第一个插件,见 vite.config.ts:

import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vite.dev/config/ export default defineConfig({ plugins: [react()], })

这份配置是全仓库最核心的 Vite 配置:defineConfig提供类型提示,react()插件负责开启 React Fast Refresh。开发时保存组件文件,浏览器无需整页刷新即可看到更新,这正是模板宣称“get React working in Vite with HMR”的具体实现。

选型建议:若项目追求极致的冷启动与构建速度,或团队已在使用 Rust 系工具链(Oxc / Rolldown),优先@vitejs/plugin-react;若需要与 SWC 生态(如 swc-node 做其他编译任务)保持一致,则选@vitejs/plugin-react-swc。两者在功能上对普通 React 应用等价,差异主要体现在底层编译器与生态偏好。

三、React Compiler:模板为何默认关闭,以及如何开启

模板文档特别说明:React Compiler 在此模板中默认未启用,原因是它会对开发与构建性能产生影响。React Compiler 是 React 官方的“自动记忆化(auto-memoization)”编译器,可在编译期自动为组件补上记忆化逻辑,减少不必要的重渲染,从而替代一部分手写useMemo/useCallback的工作。

对于 todo-app 这类以useState为主、状态提升层级简单的应用,React Compiler 的收益有限,而引入它需要在vite.config.ts中增加编译插件并承受额外的编译开销,因此模板保持关闭是合理的默认值。文档给出的开启方式是参考官方安装指引:在 Vite 工程中接入对应的 React Compiler 插件(babel-plugin-react-compiler或 Vite 官方推荐的接入方式),并确保项目满足 React 19 的前置版本要求。

适用前提:React Compiler 适合重渲染瓶颈明显、组件树较深的中大型应用;在追求开发体验与构建速度的轻量模板中,保持关闭、按需手写记忆化是更务实的做法。仓库内的 todo-app 也正因不依赖该能力,才维持了dev/build极快的响应。

四、Oxlint 工程化:从默认规则到类型感知 lint

模板在 devDependencies 中引入了oxlint(Rust 版 linter,规则兼容 ESLint 常用集合),并提供lint脚本。模板文档建议:生产级应用应开启 type-aware(类型感知)lint 规则,做法是安装oxlint-tsgolint并在.oxlintrc.json中做如下扩展:

{ "$schema": "./node_modules/oxlint/configuration_schema.json", "plugins": ["react", "typescript", "oxc"], "options": { "typeAware": true }, "rules": { "react/rules-of-hooks": "error", "react/only-export-components": ["warn", { "allowConstantExport": true }] } }

逐项解读这份配置:

  • $schema:指向本地安装的 Oxlint 配置 JSON Schema,让编辑器在编辑.oxlintrc.json时获得自动补全与校验;
  • plugins:启用react(React 专属规则)、typescript(TS 类型相关规则)、oxc(Oxc 编译前端提供的规则)三组插件;
  • options.typeAware: true:开启类型感知模式,使部分需要 TS 类型信息的规则(如未使用变量、类型窄化相关的 lint)可以正常工作,代价是 lint 时需要额外的类型信息解析;
  • react/rules-of-hooks: "error":将 Hooks 规则(只能在组件/自定义 Hook 顶层调用 Hooks)设为 error 级别。这条规则对本文的 Todo App 尤其相关——TodoItem.tsx 中useState与useEffect都位于组件顶层,恰好是“rules-of-hooks”的合规写法;
  • react/only-export-components: ["warn", { "allowConstantExport": true }]:要求一个文件只导出组件(避免混入非组件导出导致 Fast Refresh 失效),并允许常量导出(allowConstantExport: true),这样像export const INITIAL_TODOS这类常量不会触发警告。

对照仓库源码可以验证该配置的价值:todo-app 的所有组件文件(TodoForm、TodoList、TodoItem)都严格遵循“一文件一组件 + 仅导出组件”的约定,类型定义则独立放在 src/types/todo.ts,与组件文件分离——这正是only-export-components规则鼓励的代码组织方式。

注意:开启typeAware后,oxlint 需要能解析项目的tsconfig以获得类型信息,因此需确保.oxlintrc.json与 tsconfig.json(含tsconfig.app.json与tsconfig.node.json两个子引用)配合良好。本仓库的 TypeScript 配置采用moduleResolution: "bundler"、jsx: "react-jsx"、noEmit: true等现代 Vite 工程标配,见 tsconfig.app.json,与 Oxlint 的类型感知模式天然兼容。

五、模板之上的真实业务:Todo App 的增删改查源码解剖

模板文档解决了“工具链怎么配”的问题,而仓库把这个脚手架用在了实处——一个支持新增、删除、编辑的 Todo 应用。下面结合源码梳理这套组件的组织方式,作为模板最佳实践的落地范例。

5.1 数据模型与状态提升

类型定义非常克制,仅两个字段,见 src/types/todo.ts:

export type Todo = { id: number, label: string }

应用根组件 src/App.tsx 是唯一持有 todos 状态的地方(状态提升到顶层,子组件通过回调修改),并维护了nextId计数器生成自增 id:

let nextId = 0; const INITIAL_TODOS: Todo[] = [ { id: nextId++, label: 'one' }, { id: nextId++, label: 'two' }, { id: nextId++, label: 'three' }, ]; export default function App() { const [todos, setTodos] = useState<Todo[]>(INITIAL_TODOS); const addTodo = (label: string) => { setTodos((todos) => [...todos, {id: nextId++, label}]); } const deleteTodo = (id: number) => { setTodos((todos) => todos.filter((todo) => todo.id !== id)); } const editTodo = (id: number, label: string) => { setTodos((todos) => todos.map((todo) => todo.id === id ? {...todo, label} : todo )); } // ... }

三个操作全部使用函数式setTodos(基于上一次状态计算新状态),保证连续多次更新时的正确性;addTodo/deleteTodo/editTodo分别对应数组的展开追加、filter与map三种不可变更新模式,是 React 状态管理最经典的教学案例。这与模板的 Hooks + TypeScript 组合完全吻合:类型系统保障label: string、id: number的入参安全。

5.2 表单组件:受控输入与空值拦截

src/components/TodoForm.tsx 通过onAdd回调把新标签传给父组件,内部用useState维护输入框内容(受控组件):

export function TodoForm({onAdd}: TodoFormProps) { const [newTodo, setNewTodo] = useState(""); const handleSubmit = () => { const label = newTodo.trim(); if(!label) { return; // 空输入直接忽略,避免产生空白待办 } onAdd(label); setNewTodo(""); // 提交后清空输入框 } // <input value={newTodo} onChange=... /> + Submit 按钮 }

值得注意的实现细节:trim()之后若为空则直接return,从源头杜绝空白待办;按钮同时绑定了onClick与onKeyDown(Enter 键),兼顾鼠标与键盘操作。这是模板最小化哲学下“代码虽少,行为完整”的体现。

5.3 列表与单条编辑:条件渲染 + useEffect 同步

src/components/TodoList.tsx 处理空态与渲染:列表为空时展示No todos found,否则用todos.map渲染TodoItem,并以key={todo.id}保证列表 diff 稳定。

单条编辑逻辑位于 src/components/TodoItem.tsx,是组件中最具教学价值的部分:

export function TodoItem({todo, onDelete, onEdit}: TodoItemProps) { const [isEditing, setIsEditing] = useState(false); const [label, setLabel] = useState(todo.label); useEffect(() => { setLabel(todo.label); // 外部 label 变化时同步到本地编辑态 }, [todo.label]); // ... }

这里展示了两个典型模式:

  1. 条件渲染切换编辑态:isEditing为 true 时渲染输入框 + Save/Cancel 按钮,否则渲染纯文本 + Edit/Delete 按钮;
  2. useEffect同步派生状态:编辑框的本地label状态需要跟随todo.label更新,因此用useEffect在todo.label变化时重置——这正是模板 README 提到 Oxlintrules-of-hooks规则所守护的写法(Hooks 必须无条件、按固定顺序在顶层调用)。

Save 时同样先trim()并拦截空值,再调用onEdit(todo.id, newLabel)并把isEditing置回 false;Cancel 则丢弃编辑内容,setLabel(todo.label)恢复原值。

六、从模板到生产:落地清单

综合模板文档与仓库源码,将一个基于本模板的工程推向生产环境时,建议按以下清单核对:

  1. 类型检查前置:保持build脚本中的tsc -b && vite build顺序,让类型错误在打包前暴露;
  2. 开启类型感知 lint:按上文.oxlintrc.json扩展oxlint-tsgolint,并把react/rules-of-hooks设为 error;
  3. 组件组织约定:遵守only-export-components,组件文件只导出组件、类型定义独立成types/*.ts,参考本仓库 src/types 与 src/components 的划分;
  4. 状态更新方式:所有setState优先使用函数式更新,确保依赖最新状态(见 App.tsx 的三种写法);
  5. HMR 友好:若接入 React Compiler,需评估其对 dev/build 性能的影响,本文第 3 节已说明模板默认关闭的原因与适用场景。

七、小结

本仓库的 todo-app 是“官方模板 README + 真实业务实现”的绝佳组合:README 解释了脚手架的能力边界(HMR、Oxlint、React Compiler 取舍),而源码则示范了在这套工具链下如何组织类型、组件与状态。无论你是想快速启动一个新 React 项目,还是想理解 Vite + React 19 + TypeScript + Oxlint 的现代工程化配置,都可以直接以 coding-projects/todo-app 为起点,把这里的vite.config.ts、.oxlintrc.json与组件分层模式复用到自己的项目中。

  • 前端
  • 教程
  • 文档

【免费下载链接】reactjs-interview-questions

List of top 500 ReactJS Interview Questions & Answers....Coding exercise questions are coming soon!!

项目地址:https://gitcode.com/GitHub_Trending/re/reactjs-interview-questions
点击查看免费下载
上一篇:X-AnyLabeling 自定义模型接入与部署指南:内置模型加载、ONNX 适配与 TensorRT 推理全流程
下一篇:北京邮电大学本科毕业设计LaTeX模板终极指南:从零基础到专业排版

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表