React 快速入门:Vite 搭建项目、JSX 语法、渲染原理

1 阅读3分钟

一、Vite 创建 React 项目

1.1 创建项目

npm create vite@latest my-app -- --template react
# TypeScript 项目用:--template react-ts

cd my-app
npm install
npm run dev        # 启动开发服务器
npm run build      # 生产构建

1.2 入口挂载(与 Vue 的差异)

// src/main.jsx —— React 用 createRoot 创建根节点
import { createRoot } from "react-dom/client";
import App from "./App.jsx";

createRoot(document.getElementById("root")).render(<App />);

对比 Vue:Vue 是 createApp(App).mount("#app");React 是 createRoot(...).render(...),本质都是"挂载组件树"。


二、项目目录结构解读

my-app/
├── index.html          # 唯一 HTML,含 <div id="root">
├── vite.config.js      # Vite 配置
├── public/             # 静态资源(原样拷贝)
└── src/
    ├── main.jsx        # 入口:createRoot 渲染
    ├── App.jsx         # 根组件
    ├── components/     # 组件目录
    ├── assets/         # 参与构建的资源
    └── index.css       # 全局样式

.jsx 表示文件内含 JSX 语法;React 项目无模板文件,一切皆组件


三、JSX 语法规则:与 HTML 的区别

JSX 是 JavaScript 的语法扩展,本质是 React.createElement() 的语法糖——在 JS 里写类似 HTML 的结构,但有几处关键差异:

对比项HTMLJSX
类名classclassName(class 是 JS 保留字)
标签属性forhtmlFor(label 用)
事件onclick="fn()"onClick={fn}(驼峰 + 传函数)
内联样式style="color:red"style={{ color: "red" }}(对象 + 驼峰)
标签闭合部分可不闭合必须闭合<img /><input />
注释<!-- -->{/* ... */}
export default function App() {
  return (
    <div className="app">
      <h1>Hello React</h1>
      {/* JSX 注释写法 */}
      <button onClick={() => alert("点击")}>按钮</button>
      <img src="/logo.png" alt="logo" style={{ width: 100 }} />
    </div>
  );
}

其他 JSX 规则

  • 只能返回一个根节点(Vue3 支持多根,React 仍要求单根,可用 Fragment <>...</> 包裹);
  • JSX 表达式用 { } 包裹;
  • 属性值为字符串用引号,为表达式用 {}
  • 变量命名采用驼峰。

四、变量与表达式渲染

4.1 渲染变量与表达式

const user = { name: "张三", age: 18 };
const isLogin = true;

export default function App() {
  return (
    <div>
      <p>{user.name}</p>                    {/* 变量 */}
      <p>{user.age + 1}</p>                 {/* 运算 */}
      <p>{isLogin ? "已登录" : "未登录"}</p>  {/* 三元 */}
      <p>{formatDate(new Date())}</p>       {/* 函数调用 */}
      <p>{[1, 2, 3].join("-")}</p>          {/* 方法调用 */}
    </div>
  );
}

function formatDate(d) {
  return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
}

4.2 渲染规则

  • {null}{undefined}{false}{true} 不渲染任何内容
  • {0} 会渲染 "0"(数字 0 是有效内容)——条件渲染时注意。

五、条件渲染、列表渲染

5.1 条件渲染三种写法

// 写法一:&& 逻辑与(右侧为 false 时不渲染)
{isLogin && <p>欢迎回来</p>}

// 写法二:三元表达式
{isLogin ? <p>已登录</p> : <button onClick={goLogin}>去登录</button>}

// 写法三:提前 return(复杂分支)
function Panel({ status }) {
  if (status === "loading") return <p>加载中…</p>;
  if (status === "error") return <p>加载失败</p>;
  return <p>加载完成</p>;
}

5.2 列表渲染(map + key)

const list = [
  { id: 1, name: "React" },
  { id: 2, name: "Vue" },
];

export default function App() {
  return (
    <ul>
      {list.map((item) => (
        <li key={item.id}>{item.name}</li>   {/* key 必须且唯一 */}
      ))}
    </ul>
  );
}

key 的作用:帮助 React 识别节点复用与重建;不要用 index 做 key(插入/删除时渲染错位)。


六、JSX 常见报错踩坑

现象解决
用了 class 而不是 className样式不生效、控制台警告全部改为 className
标签未闭合编译报错单标签必须自闭合 <img />
key 缺失/重复控制台警告、列表更新错乱加稳定唯一 key
表达式用 {} 误写成字符串渲染出字面量{count} 而非 "count"
style 传字符串报错或不生效style={{ color: "red" }} 对象语法
多根节点编译报错"Adjacent JSX elements"用 Fragment <>...</> 包裹
注释用 HTML 语法显示为文本{/* ... */}

七、总结

  • 搭建:Vite 模板 + createRoot().render(),无模板文件、一切皆组件;
  • JSX:JS 里的类 HTML,className、驼峰事件、{ } 表达式、必须闭合;
  • 渲染{变量/表达式},null/undefined/false 不渲染;
  • 条件/列表&&、三元、提前 return;map + key
  • 对比 Vue:模板指令(v-if/v-for)→ 纯 JS 表达式(&&、map);响应式 → 显式 setState;
  • 踩坑:className、闭合、key、多根是四大高频报错。