React 中使用 JSX 编写标签:从语法糖到最佳实践

56 阅读1分钟

一篇博客带你吃透「为什么看起来像 HTML,其实是 JavaScript」


1. JSX 是什么?

  • 官方定义:JavaScript + XML 的语法扩展
  • 本质React.createElement(component, props, ...children)语法糖
  • 编译时由 Babel/SWC 转译成纯 JS,浏览器不认识 JSX,只认识 React.createElement。

2. Hello JSX:一行代码看透转译

// 你写的 JSX
const element = <h1 className="title">Hello, JSX!</h1>;

// Babel 转译结果
const element = React.createElement(
  'h1',
  { className: 'title' },
  'Hello, JSX!'
);

3. JSX 与 HTML 的 5 处关键差异

场景HTMLJSX
属性名classclassName
自闭合<img><img />
样式style="color:red"style={{color:'red'}}
表达式不支持{1 + 2}
注释<!-- -->{/* 注释 */}

4. 在标签里嵌入任意 JavaScript

function Avatar({ user }) {
  return (
    <img
      src={user.avatar}
      alt={user.name}
      style={{
        borderRadius: user.isVip ? '50%' : 0,
        width: user.isVip ? 80 : 40
      }}
    />
  );
}

5. 条件渲染与列表渲染

条件

{isLoggedIn ? <LogoutBtn /> : <LoginBtn />}

列表

<ul>
  {todos.map(todo =>
    <li key={todo.id}>{todo.text}</li>
  )}
</ul>

6. Fragment 与空标签:不写多余 DOM

// ❌ 会多一层 <div>
return (
  <div>
    <Header />
    <Main />
  </div>
);

// ✅ 不额外生成节点
return (
  <>
    <Header />
    <Main />
  </>
);

7. 自闭合组件与 Children

// 无 children
<Icon type="close" />

// 有 children
<Button>
  {loading ? 'Loading...' : 'Submit'}
</Button>

8. 常见错误 & 调试技巧

报错信息原因解决
JSX expressions must have one parent多个根节点<><div> 包裹
Expected corresponding JSX closing tag标签未闭合检查 <img><img />
Cannot use 'class' as a JSX prop误用 HTML 属性改为 className

9. Vite 项目实战:一行命令体验 JSX

npm create vite@latest jsx-demo --template react-ts
cd jsx-demo && npm i && npm run dev

App.tsx 里随意改 JSX,保存即热更新,体验 0 延迟。


10. 小结:JSX 记忆口诀

“看上去 HTML,本质是 JS;花括号里写 JS,首字母大写是组件。”