[React源码系列1]React中的JSX

454 阅读3分钟

一、什么是JSX

JSX是一种类似于XML的语法,他可以被转换成合法的JavaScript,通常会理解成JavaScript XML,但是它的转移语法通常会按不同的依据实现,前端中常见的是通过Bable来实现转换的。JSX是因React框架而流行。

二、React中的JSX

JSX在React中的表现可以理解为一种语法糖,它的主要作用是让我们能够在JS代码中编写HTML标记,最终会通过Bable.js转译成createElement语法,再转化成普通的JS对象或者说是React元素

2.1 React元素

  • 元素是描述React应用的最小单位,通过元素来描述页面上呈现的内容
  • React元素本质上是普通JS对象,它的作用是用来描述ReactDOM并确保最终能够渲染成真实DOM
  • React元素本身是不可变的

JSX.png

2.2 JSX表达式

通常在JSX中为元素添加属性时,可以通过引号来指定属性值为string字面量

const element = <div tabIndex="0"></div>;

在大部分情况下我们会使用 { } 来为属性值中插入一个JavaScript代码

const element = <img src={user.avatarUrl}></img>;

2.3 JSX属性

JSX在不是html,它在表现和语法上更加偏向于JavaScript,所以在JSX中的属性通常使用小驼峰命名来定义属性的名字,这样做也是为了更好的避免在程序中出现关键字

  • class需要写成classNamefor需要写成htmlFor

2.4 JSX表示对象

babel的转移发生在代码执行之前,所以本质上jsx就是createElement的执行结果,即对象。所以JSX是可以赋值给变量,作为参数传入,或作为返回值。

三、深入JSX

  • JSX 只是React.createElement(conponent,props,...children)函数的语法糖
  • 大写的开头的JSX元素代表它是React组件,用户自定义组件必须要使用大写开头
  • React必须在作用域内,由于 JSX 会编译为 React.createElement 调用形式,所以 React 库也必须包含在 JSX 代码作用域内
  • JSX 中的props接受JavaScript表达式,注意iffor不是JS的表达式
  • Props默认值是true
// 以下的代码是等价的
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
  • 属性展开:如果已有了一个props对象,你就可以使用...展开运算符将对象整个传递给 JSX
// 以下的代码是等价的
function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}
  • JSX中的子元素

    • 字符串字面量类型子元素,在转译的时候会将首尾的空格和空行都清除
    • JSX 子元素允许由多个 JSX元素 组成
    <MyContainer>
      <MyFirstComponent />
      <MySecondComponent />
    </MyContainer>
    
    • JavaScript表达式可以作为子元素
    // 以下的代码是等价的
    <MyComponent>foo</MyComponent>
    <MyComponent>{'foo'}</MyComponent>
    
    • 函数作为子元素,只要返回值是一个合法的JSX对象
    • 布尔类型Nullundefined是合法的 JSX 但是在渲染的时候会被忽略
    • &&三元运算符
    // 只有在 showHeader 为true的时候,才会渲染<Header />组件
    <div>
      {showHeader && <Header />}	
      <Content />
    </div>
    
    <div>
      {showHeader ? <Header /> : null;}	
      <Content />
    </div>
    

四、React17的JSX转换

React17 中使用 JSX 已经无需导入React了,官方通过与Babel合作提供了一个全新的JSX转换版本,但是需要配合TypeScript 4.1+版本和Babel 7.9.0+使用。

新JSX.png

需要注意的是,直接移除React可能会触发ESLint报错,需要我们关闭或删除react/jsx-uses-reactreact/react-in-jsx-scope校验