React之JSX原理

摘抄自React小书

为了让大家深刻理解 JSX 的含义。有必要简单介绍了一下 JSX 稍微底层的运作原理,这样大家可以更加深刻理解 JSX 到底是什么东西,为什么要有这种语法,它是经过怎么样的转化变成页面的元素的。

思考一个问题:如何用 JavaScript 对象来表现一个 DOM 元素的结构,举个例子:

<div class='box' id='content'>
  <div class='title'>Hello</div>
  <button>Click</button>
</div>

每个 DOM 元素的结构都可以用 JavaScript 的对象来表示。你会发现一个 DOM 元素包含的信息其实只有三个:标签名,属性,子元素。

所以其实上面这个 HTML 所有的信息我们都可以用合法的 JavaScript 对象来表示:

{
  tag: 'div',
  attrs: { className: 'box', id: 'content'},
  children: [
    {
      tag: 'div',
      arrts: { className: 'title' },
      children: ['Hello']
    },
    {
      tag: 'button',
      attrs: null,
      children: ['Click']
    }
  ]
}

你会发现,HTML 的信息和 JavaScript 所包含的结构和信息其实是一样的,我们可以用 JavaScript 对象来描述所有能用 HTML 表示的 UI 信息。但是用 JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。

于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。

上面的代码:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'

class Header extends Component {
  render () {
    return (
      <div>
        <h1 className='title'>React 小书</h1>
      </div>
    )
  }
}

ReactDOM.render(
  <Header />,
  document.getElementById('root')
)

经过编译以后会变成:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'

class Header extends Component {
  render () {
    return (
     React.createElement(
        "div",
        null,
        React.createElement(
          "h1",
          { className: 'title' },
          "React 小书"
        )
      )
    )
  }
}

ReactDOM.render(
  React.createElement(Header, null), 
  document.getElementById('root')
);

React.createElement 会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等。这样的代码就是合法的 JavaScript 代码了。所以使用 React 和 JSX 的时候一定要经过编译的过程。

这里再重复一遍:所谓的 JSX 其实就是 JavaScript 对象。每当在 JavaScript 代码中看到这种 JSX 结构的时候,脑子里面就可以自动做转化,这样对你理解 React.js 的组件写法很有好处。

有了这个表示 HTML 结构和信息的对象以后,就可以拿去构造真正的 DOM 元素,然后把这个 DOM 元素塞到页面上。这也是我们最后一段代码中 ReactDOM.render 所干的事情:

ReactDOM.render(
  <Header />,
  document.getElementById('root')
)

ReactDOM.render 功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上(在这里是 id 为 rootdiv 元素)。

所以可以总结一下从 JSX 到页面到底经过了什么样的过程:

这里写图片描述

有些同学可能会问,为什么不直接从 JSX 直接渲染构造 DOM 结构,而是要经过中间这么一层呢?

第一个原因是,当我们拿到一个表示 UI 的结构和信息的对象以后,不一定会把元素渲染到浏览器的普通页面上,我们有可能把这个结构渲染到 canvas 上,或者是手机 App 上。所以这也是为什么会要把 react-dom 单独抽离出来的原因,可以想象有一个叫 react-canvas 可以帮我们把 UI 渲染到 canvas 上,或者是有一个叫 react-app 可以帮我们把它转换成原生的 App(实际上这玩意叫 ReactNative)。

第二个原因是,有了这样一个对象。当数据变化,需要更新组件的时候,就可以用比较快的算法操作这个 JavaScript 对象,而不用直接操作页面上的 DOM,这样可以尽量少的减少浏览器重排,极大地优化性能。这个在以后的章节中我们会提到。

总结
要记住几个点:

  1. JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并不是 HTML。
  2. React.js 可以用 JSX来描述你的组件长什么样的。
  3. JSX 在编译的时候会变成相应的 JavaScript 对象描述。
  4. react-dom 负责把这个用来描述UI 信息的 JavaScript 对象变成 DOM 元素,并且渲染到页面上。
<think>我们正在讨论ReactJSX的常用语法。根据提供的引用内容,我们可以总结以下几点: 1. JSX是JavaScript XML的缩写,允许在JavaScript中写类似HTML的结构。 2. JSX提高了代码可读性和可维护性,使构建UI更直观。 3. JSX编译时被转换成纯JavaScript代码,执行更快,且是类型安全的。 4. JSX语法中必须有一个根元素包裹,否则会报错。 5. 在JSX中可以使用JavaScript表达式,用大括号{}包裹。 接下来,我将按照常用语法点进行详细说明: ### 1. JSX基本元素 JSX的基本元素类似于HTML标签,但要注意一些关键区别: - 使用小驼峰命名法(camelCase)定义属性名,例如`className`代替`class`,`htmlFor`代替`for`(label标签)。 - 自闭合标签必须以`/>`结束,如`<img />`。 示例: ```jsx const element = <h1 className="greeting">Hello, world!</h1>; ``` ### 2. 在JSX中嵌入表达式 在JSX中,你可以通过大括号`{}`嵌入任何有效的JavaScript表达式,包括变量、函数调用、算术运算等。 示例: ```jsx const name = 'John'; const element = <h1>Hello, {name}</h1>; ``` ### 3. JSX中的条件渲染 在JSX中,可以使用条件语句(如三元运算符)或逻辑与(&&)运算符进行条件渲染。 示例(三元运算符): ```jsx const isLoggedIn = true; const greeting = <div>{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}</div>; ``` 示例(逻辑与): ```jsx const unreadMessages = ['msg1', 'msg2']; const messageCount = unreadMessages.length; const alert = <div>{messageCount > 0 && <h2>You have {messageCount} unread messages.</h2>}</div>; ``` ### 4. JSX中的列表渲染 使用数组的`map()`方法将数组转换为JSX元素列表。注意:每个列表项必须有一个唯一的`key`属性(通常是唯一ID),这有助于React高效更新列表。 示例: ```jsx const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}>{number}</li> ); ``` ### 5. JSX中的样式 有两种方式定义样式: - **内联样式**:使用对象形式,样式属性名使用小驼峰命名法(如`backgroundColor`),值用字符串表示。 - **外部CSS类**:通过`className`属性引用外部CSS类。 示例(内联样式): ```jsx const divStyle = { color: 'blue', backgroundColor: 'lightgray' }; const element = <div style={divStyle}>Hello Style!</div>; ``` ### 6. JSX中的事件处理 事件处理函数以小驼峰形式指定(如`onClick`),并将函数引用(而非字符串)作为值传递。 示例: ```jsx function handleClick() { console.log('Button clicked'); } const button = <button onClick={handleClick}>Click Me</button>; ``` ### 7. JSX中的注释 在JSX中写注释需要用大括号包裹,使用`/* */`或`//`。 示例: ```jsx <div> {/* 这是单行注释 */} { // 这也是单行注释,但注意换行问题 } <p>Hello World</p> </div> ``` ### 8. JSX的根元素规则 JSX表达式必须有一个顶层父元素。如果不想添加额外标签,可以使用`<React.Fragment>`(或简写`<>`)包裹,这样不会在DOM中增加额外节点。 示例: ```jsx const fragment = ( <> <h1>Title</h1> <p>Content</p> </> ); ``` ### 9. JSX与HTML的区别 - 属性名使用小驼峰:`tabIndex`(JSX) vs `tabindex`(HTML)。 - 某些属性名不同:如`className`(JSX)代替`class`(HTML)。 - 事件处理函数必须传入函数,而不是字符串。 ### 小结 JSXReact的核心特性之一,它使得编写组件更加直观。通过掌握上述常用语法,你可以更高效地使用React开发应用。记住,JSX最终会被编译为`React.createElement()`函数调用,因此它本质上仍然是JavaScript。 §§相关问题§§ 1. JSX和HTML有什么区别? 2. 为什么在JSX中列表项需要key属性? 3. 如何在JSX中处理表单元素? 4. 如何避免JSX注入攻击(XSS)? 5. JSX中的`children`属性有什么作用?</think>### React JSX 常用语法教程 JSX(JavaScript XML)是React的核心语法扩展,允许在JavaScript中直接编写类似HTML的结构。以下是常用语法详解: #### 一、基础语法 1. **基本元素** 类似HTML标签,但需遵守XML规则(必须闭合标签): ```jsx const element = <h1 className="title">Hello JSX</h1>; // className 代替 class ``` 2. **根元素规则** 组件必须返回**单个根元素**,可用`<Fragment>`或`<></>`避免额外DOM节点: ```jsx return ( <> {/* 空标签相当于 Fragment */} <Header /> <MainContent /> </> ); ``` #### 二、嵌入表达式 用`{}`包裹JavaScript表达式: ```jsx const user = { name: "Alice" }; const element = ( <div> <p>计算: {5 + 3}</p> {/* 输出: 8 */} <p>用户: {user.name.toUpperCase()}</p> {/* 输出: ALICE */} <p>时间: {new Date().toLocaleTimeString()}</p> </div> ); ``` #### 三、属性处理 1. **动态属性值** ```jsx const url = "https://example.com"; const img = <img src={url} alt="示例" />; ``` 2. **布尔属性** 省略值时默认为`true`: ```jsx <button disabled>不可点击</button> // 等同于 disabled={true} ``` #### 四、条件渲染 1. **三元表达式** ```jsx <div>{isLoggedIn ? <LogoutButton /> : <LoginButton />}</div> ``` 2. **&& 短路运算** ```jsx {hasUnread && <Badge count={unreadCount} />} ``` #### 五、列表渲染 使用`map()`并添加唯一`key`: ```jsx const items = ["React", "Vue", "Angular"]; const list = ( <ul> {items.map((item, index) => ( <li key={index}>{item}</li> // key 提高渲染性能 ))} </ul> ); ``` #### 六、样式处理 1. **内联样式** 使用驼峰命名法的样式对象: ```jsx const style = { backgroundColor: "black", padding: "10px" }; <div style={style}>内容</div> ``` 2. **CSS类名** 通过`className`属性绑定: ```jsx <div className="container active">...</div> ``` #### 七、事件处理 驼峰命名法 + 函数引用(非字符串): ```jsx function handleClick() { alert("按钮被点击"); } <button onClick={handleClick}>点击</button> ``` #### 八、注释语法 需包裹在`{}`中: ```jsx <div> {/* 这是单行注释 */} { // 多行注释 } </div> ``` #### 九、JSX 原理 JSX 会被编译为 `React.createElement()` 调用: ```jsx // JSX 代码 <h1 id="title">Hello</h1> // 编译React.createElement("h1", { id: "title" }, "Hello"); ``` ### 注意事项 1. 避免使用JS关键字属性名(如`class` → `className`,`for` → `htmlFor`) 2. 自定义组件必须以**大写字母开头**(区分HTML标签) 3. 表达式中的`false`、`null`、`undefined`不会渲染 > JSX 使React组件更直观,编译优化后执行更快,并在编译阶段捕获类型错误[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值