jsx介绍

jsx是一种JavaScript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起就是一段XML语法,用于描述UI界面,并且可以和JavaScript代码结合使用。

比起vue中的模板语法,更加灵活,且不需要学习模板语法中的特定标签,比如:v-ifv-forv-bind等,而是直接使用JavaScript语法就可以实现这些标签的功能。

为何React中编写UI界面需要使用jsx语法呢

因为原生html和js两者是密不可分的两个部分,比如操作html元素时:

  1. 使用js选中元素,然后修改元素;
  2. 元素上绑定有事件时,需要绑定对应的事件函数;
  3. js中某些数据发生变化时,需要修改html元素。

索性,React直接将两者组合在一起进行管理。

jsx语法

书写规范

  1. 顶层只允许有一个根元素,和vue2类似;
  2. 为了方便阅读,通常在外层包裹一个 ()
  3. 可以使用单标签和双标签,但是单标签一定要包含结束符号,如:<button/>
// 定义App根组件
class App extends React.Component {
render() {
{/* 2.return外层,最好包裹一个() */}
return (
{/* 1.顶层只允许有一个根元素 */}
<div>
{/* 3.支持单标签和双标签 */}
<h2>h2</h2>
<br/>
</div>
</div>
)
}
}

基本使用

1.添加注释

在jsx中,添加注释使用这样的格式:

{/* 注释内容 */}

2.使用变量

  1. 当变量是Number、String、Array类型时,可以直接显示
  2. 当变量是null、undefined、Boolean类型时,内容显示为空,如果需要显示,需要转换为字符串;
  3. Object对象类型不能作为子元素(not valid as a React child)
class App extends React.Component {
constructor() {
super()
this.state = {
// Number/String/Array类型
name: 'easylee',
age: 18,
movies: ['xxx', 'xxx'], // null/undefined/boolean类型
varNull: null,
varUndefined: undefined,
varBoolean: true, // Object对象
friends: { name: 'foo' },
}
} render() {
const { name, age, movies } = this.state
const { varNull, varUndefined, varBoolean } = this.state
const { friends } = this.state return (
<div>
{/* 正常显示 */}
<h2>name: {name}</h2>
<h2>age: {age}</h2>
<h2>movies: {movies}</h2> {/* 显示为空 */}
<h2>null: {varNull}</h2>
<h2>undefined: {varUndefined}</h2>
<h2>Boolean: {varBoolean}</h2> {/* 显示为字符串 */}
<h2>null: {varNull + ''}</h2>
<h2>undefined: {String(varUndefined)}</h2>
<h2>Boolean: {varBoolean.toString()}</h2> {/* 对象不允许直接作为子元素,必须具体到对象的属性 */}
{/* <h2>friends: {friends}</h2> */}
<h2>friends: {friends.name}</h2>
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<App />)

3.使用表达式

和vue中使用模板语法一样,只有可以放在 return 后的语句,都是表达式,可以直接在jsx中使用。

主要包含:

  1. 运算表达式;
  2. 三元表达式;
  3. 可执行函数。
class App extends React.Component {
constructor() {
super()
this.state = {
firstName: 'easy',
lastName: 'lee',
age: 18,
movies: ['foo', 'bar'],
}
} getMovies() {
return this.state.movies
} render() {
const { firstName, lastName, age } = this.state return (
<div>
{/* 表达式 */}
<h2>{1 + 1}</h2>
<h2>{firstName + ' ' + lastName}</h2>
<h2>{age >= 18 ? '成年' : '未成年'}</h2>
<h2>{this.getMovies()}</h2>
</div>
)
}
}

4.绑定属性

给html元素或者组件添加属性,和直接使用变量类似,都使用{}包裹即可,绑定 classstyle 有一点不同:

  1. 基本属性,直接绑定即可;
  2. class属性,需要使用 className 代替 class ,因为class在js中也表示类;
  3. style属性,需要传递一个对象。
class App extends React.Component {
constructor() {
super() this.state = {
title: 'title',
imgUrl: 'http://xxx.xxx.xxx',
isActive: true,
objStyle: { color: 'red', fontSize: '20px' },
}
} render() {
const { title, imgUrl, isActive, objStyle } = this.state
const className = `foo ${isActive ? 'active' : ''}`
return (
<div>
{/* 基本属性绑定 */}
<h2 title={title}>h2</h2>
<img src={imgUrl} /> {/* 绑定class属性 */}
<h2 className='className'>h2</h2> {/* 绑定style属性,objStyle必须是一个对象 */}
<h2 style={objStyle}>h2</h2>
</div>
)
}
}

5.绑定事件

React中绑定事件需要使用小驼峰格式。

class App extends React.Component {
constructor() {
super() this.state = {
name: 'easylee',
}
}
btnClick() {
console.log('btnClick')
}
btnClick2() {
this.setState({
name: 'easy',
})
}
btnClick3(event, name, age) {
console.log(event, name, age)
}
render() {
return (
<div>
{/* 事件绑定基本使用 */}
<button onClick={this.btnClick}>按钮</button>
<button onClick={() => this.btnClick2()}>按钮</button>
<h2>{this.state.name}</h2> {/* 传递参数 */}
<button onClick={event => this.btnClick3(event, 'easylee', 18)}>按钮</button>
</div>
)
}
}

上例代码中,当我们绑定的函数体内部使用了this,传递给onClick的函数需要绑定指定的this,通常有下面几种方式进行绑定,原因和解决方法具体可以看:https://www.cnblogs.com/easy1996/p/17952054。

同时,给绑定函数传递参数时,onClick会默认给绑定的函数第一个参数传递 event 参数。

6.条件渲染

jsx中条件渲染可以使用多种方式:

  1. 直接使用JavaScript if进行条件判断;
  2. 使用三元运算符;
  3. 使用逻辑运算符。
class App extends React.Component {
constructor() {
super() this.state = {
isOk: true,
friend: { name: 'foo' },
}
}
render() {
const { isOk, friend } = this.state
let showContent = null
if (isOk) {
showContent = <h2>正常</h2>
} else {
showContent = <h2>异常</h2>
} return (
<div>
{/* 1.使用if进行判断,注意渲染函数中不能使用if判断,应该写在render()外 */}
<h2>{showContent}</h2> {/* 2.三元运算符 */}
<h2>{isOk ? <span>正常</span> : <span>异常</span>}</h2> {/* 3.&&逻辑与判断,为空或者undefined时,就会默认不显示 */}
<h2>{friend && <span>{friend.name}</span>}</h2>
</div>
)
}
}

7.列表渲染

列表渲染通常使用高阶函数,比如 mapfilter等,通过前面的介绍,我们知道表达式可以直接在 {} 中使用,直接使用这些高阶函数即可渲染列表。

class App extends React.Component {
constructor() {
super() this.state = {
list: [
{
name: 'easylee',
age: 18,
},
{
name: 'foo',
age: 20,
},
],
}
}
render() {
const { list } = this.state
return (
<ul>
{list.map(item => {
return (
<li key={item.name}>
<h2>name: {item.name}</h2>
<h2>age: {item.age}</h2>
</li>
)
})}
</ul>
)
}
}

上面代码中,{} 内通过高阶函数,获取到一个 li 元素数组,然后直接渲染这个数组,即完成了列表的渲染。

当然也可以把高阶函数这块代码提取到其它地方或者创建一个函数专门生成 li 元素数组。

同时需要注意,和vue一样,列表元素都需要设置一个 key ,以提高diff算法时的效率。

jsx转换原理

jsx通过babel进行转换,仅仅是一个语法糖,本质上,所有的jsx代码最终都将转换为 React.createElement(type, config, children)函数,这个函数包含三个参数:

  1. type:当前元素的类型,比如div就传div,组件就传组件名;
  2. config:当前元素的各种属性,比如class属性,src属性等;
  3. children:当前元素的下级元素,比如ul下的li,里面又是一个React.createElement(type, config, children)函数,是嵌套的结构。

以这段代码为例:

class App extends React.Component {
// ...
render() {
return (
<div>
<div className='header'>Header</div>
<ul className='Content'>
<li>列表数据1</li>
<li>列表数据2</li>
</ul>
</div>
)
}
}

render函数渲染中return的部分,最终会转换为React.createElement函数,直接放到return中,渲染结果一样:

render() {
return React.createElement(
'div',
null,
React.createElement(
'div',
{
className: 'header',
},
'Header',
),
React.createElement(
'ul',
{
className: 'Content',
},
React.createElement('li', null, '\u5217\u8868\u6570\u636E1'),
React.createElement('li', null, '\u5217\u8868\u6570\u636E2'),
),
)
}

这个代码,可以通过babel在线转换查看:Babel · The compiler for next generation JavaScript

可以直接编写 React.createElement 来生成UI界面,从而不使用babel转换。

通过上面的 React.createElement 函数,可以创建出一个 ReactElement对象,React利用ReactElement对象组成JavaScript的对象树,这个对象树就是虚拟DOM

编写jsx代码,然后调用createElement函数创建ReactElement对象,react再经过一些处理,最终使用JavaScript的createElement方法,再转换为真实DOM。

React jsx 语法解析 & 转换原理的更多相关文章

  1. React JSX语法说明

    原文:http://my.oschina.net/leogao0816/blog/379487 什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代 ...

  2. 2. React JSX语法及特点介绍

    什么是JSX         JSX 是一种类 XML 语言,全称是 JavaScript XML .React 可以不使用 JSX来编写组件,但是使用JSX可以让代码可读性更高.语义更清晰.对 Re ...

  3. React(JSX语法)-----JSX基本语法

    JSX------HTML tags vs React Components: 1.To render a html tag,just use lower-case tag names in JSX; ...

  4. 学习 React(jsx语法) + es2015 + babel + webpack

    视频学习地址: http://www.jtthink.com/course/play/575 官方地址 https://facebook.github.io/react/ 神坑: 1.每次this.s ...

  5. React(JSX语法)----动态UI

    1.React honws how to bubble and capture events according to the spec,and events passed to your event ...

  6. React(JSX语法)----JSX拼写

    注意:For DOM differences,such as the inline style attribute,check here. // bad: it displays "FIrs ...

  7. React(JSX语法)-----JSX属性

    1. if you know all the propertities that you want to place on a component ahead of time,it is easy t ...

  8. 22-React JSX语法

    React JSX语法 JSX只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,当然你想直接使用纯Javascript代码写也是可以的,只是利用JSX,组件的结构和 ...

  9. 用java实现编译器-算术表达式及其语法解析器的实现

    大家在参考本节时,请先阅读以下博文,进行预热: http://blog.csdn.net/tyler_download/article/details/50708807 本节代码下载地址: http: ...

  10. 【React 6/100】 React原理 | setState | JSX语法转换 | 组件更新机制

    ****关键字 | setState | JSX语法转换 | 组件更新机制 组件更新机制 setState() 的两个作用 修改state 更新组件 过程:父组件重新渲染时,也会重新渲染子组件,但只会 ...

随机推荐

  1. C++类内存分布+ Studio工具

    书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承.虚函数存在的情况下. 工欲善其事,必先利其器,我们先用好Visual Stu ...

  2. 实训——基于大数据Hadoop平台的医疗平台项目实战

    文章目录 医疗平台项目描述 数据每列的含义 数据分析业务需求 架构图 成果图 环境搭建 非常感谢各位的认可,最近太多人找我问东问西,故在此进行说明一下: 首先这个是在Linux上基于Hadoop的搭建 ...

  3. Redis系列之——持久化

    一 持久化的作用 1.1 什么是持久化 redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上 1.2 持久化的实现方式 快照:某时某刻数据的一个完成备份, -mysql的Dump -re ...

  4. 基于 P-Tuning v2 进行 ChatGLM2-6B 微调实践

    微调类型简介 1. SFT监督微调:适用于在源任务中具有较高性能的模型进行微调,学习率较小.常见任务包括中文实体识别.语言模型训练.UIE模型微调.优点是可以快速适应目标任务,但缺点是可能需要较长的训 ...

  5. 栈溢出-GOT表劫持测试

    1.目标程序源代码 char name[64]; int main(){ int unsigned long long addr; setvbuf(stdin,0,2,0); setvbuf(stdo ...

  6. Unity - Windows获取屏幕分辨率、可用区域

    直接搜索最多的就是使用System.Windows.Form.Screen类,但因为unity用的是mono,不能正常使用这个方法 可使用win32api获取,这里只尝试了获取主要屏幕的分辨率,而且没 ...

  7. Spring ---三种注入方式

    循环依赖这个问题,按理说我们在日常的程序设计中应该避免,其实这个本来也是能够避免的.不过由于总总原因,我们可能还是会遇到一些循环依赖的问题,特别是在面试的过程中,面试考察循环依赖,主要是想考察候选人对 ...

  8. 使用Github Copilot生成单元测试并执行

    上一篇文章我们介绍了 使用Github Copilot完成代码编写 本文我们继续使用Github Copilot在已有代码的基础上生成代码测试并执行. 一.先说一下代码的背景 需要上需要提供一个度量衡 ...

  9. GitHub Actions 入门指南

    前言 GitHub Actions 可以构建一组自动化的工作流程,并提供了拉取请求.合并分支等事件来触发他们.一般成熟的开源项目会在每个版本发布时提供 releases ,它就是通过 Actions ...

  10. Modbus通用串口转PROFINET IO网关TS-180 在锅炉厂智能温湿度监控系统中的应用

    背景: 现代科学技术和工业的迅速发展,不断促进着自动化控制技术及设备通信技术的创新和发展.当前,PLC.DCS.智能仪表等已广泛应用到现场生产控制系统中,本应用案例是在锅炉行业的温湿度监控系统中,西门 ...