JSX 是 JavaScript XML 的简写,表示可以在 JavaScript 代码中写 XML(HTML) 格式的代码。
优势:声明式语法更加直观,与 HTML 结构相同,降低了学习成本,提高了开发效率,JSX 是 React 的核心之一。
JSX 基本使用
- 使用 JSX 创建 React 元素
const title = <h1>Hello JSX</h1>
- 使用 createRoot() 方法渲染 React 元素到页面中
// createRoot(渲染到哪儿).render(渲染谁)
createRoot(document.querySelector('#root')).render(title)
换句话说,JSX 并不是标准的 ECMAScript 语法,为什么 React 脚手架中可以直接使用 JSX 呢?
JSX 需要使用 Babel 编译成 React.createElement()
的形式,然后配合 React 才能在浏览器中使用,而 create-react-app
脚手架中已经内置了 Babel 及相关配置。
JSX 使用注意事项
- 必须有 1 个根节点,或者虚拟根节点
<></>
、<React.Fragment></React.Fragment>
。 - 属性名一般是驼峰的写法且不能是 JS 中的关键字,例如 class 改成 className,label 的 for 属性改为
htmlFor
,colspan 改为colSpan
。 - 元素若没有子节点,可以使用单标签,但一定要闭合,例如
<span/>
。 React@16.14
之前需要先引入 React 才能使用 JSX(这个也好理解,因为 JSX 最后还是要被转成React.createElement()
的形式)。- 换行建议使用
()
进行包裹,防止换行的时候自动插入分号的 Bug。
注意: react 现有的版本中 导入和渲染的方式发生了变化 , 如下:
// React 核心包
import React from 'react'
// 渲染 React 代码到页面上
import { createRoot } from 'react-dom/client'
// React.createElement
const wrap = (
<React.Fragment>
<h3 className='test'>框架/库</h3>
{/* for 和 input 的 id 对应上,扩大点击区域 */}
<label htmlFor='input1'>姓名</label>
<input type='text' id='input1' />
<ul>
<li>vue</li>
<li>react</li>
<li>angular</li>
</ul>
{/* 没有内容,可以单标签闭合 */}
<span className='test' />
</React.Fragment>
)
// createRoot(渲染到哪儿).render(渲染谁)
createRoot(document.querySelector('#root')).render(wrap)
JSX 使用表达式
单大括号中可以使用任意的表达式(可以产生结果的式子)。
- 普通的简单数据类型。
const name = 'zs'
const age = 18
const title = (
<h1>
姓名:{name}, 年龄:{age}
</h1>
)
- 对象中的属性。
const car = {
brand: '玛莎拉蒂',
}
const title = <h1>汽车:{car.brand}</h1>
- 数组中的某一项甚至整个数组。
const friends = ['张三', '李四']
const title = <h1>汽车:{friends}</h1>
- 可以调用方法。
function sayHi() {
return '你好'
}
const title = <h1>姓名:{sayHi()}</h1>
JSX 条件渲染
// React 核心包
import React from 'react'
// 渲染 React 代码到页面上
import { createRoot } from 'react-dom/client'
/* let wrap = null
let isLoading = true
if (isLoading) {
wrap = <div>加载中...</div>
} else {
wrap = <div>加载完毕~~</div>
} */
function fn() {
/* let isLoading = true
if (isLoading) {
return <div>加载中...</div>
} else {
return <div>加载完毕~~</div>
} */
/* let isLoading = false
return isLoading ? <div>加载中...</div> : <div>加载完毕~~</div> */
let isLoading = false
return <div>{isLoading ? '加载中...' : '加载完毕~~'}</div>
}
// createRoot(渲染到哪儿).render(渲染谁)
createRoot(document.querySelector('#root')).render(fn())
JSX列表渲染
map 在 React 是使用频率最高的方法,没有之一
用法:
{ state.list.map((item)=>(
// 这里放置 要循环的内容
)}
// React 核心包
import React from 'react'
// 渲染 React 代码到页面上
import { createRoot } from 'react-dom/client'
/* const list = (
<ul>
<li>Vue</li>
<li>React</li>
<li>Angular</li>
</ul>
) */
/* const arr = ['Vue', 'React', 'Angular']
const list = (
<ul>
<li>{arr[0]}</li>
<li>{arr[1]}</li>
<li>{arr[2]}</li>
</ul>
) */
/* const arr = ['Vue', 'React', 'Angular']
const list = (
<ul>{[<li>{arr[0]}</li>, <li>{arr[1]}</li>, <li>{arr[2]}</li>]}</ul>
) */
// !问题:上面 2 种写法不具有普遍性,如果有 1000 条数据呢?
// 后端返回的数据
const arr = [
{ id: 1, name: 'Vue', title:'前端必备'},
{ id: 2, name: 'React',title:'前端进阶' },
{ id: 3, name: 'Angular',title:'暂不研究' },
]
// map 在 React 是使用频率最高的方法,没有之一
// const tempArr = arr.map((item) => <li>{item}</li>)
// const tempArr = [<li>Vue</li>, <li>React</li>, <li>Angular</li>]
// Vue => :key="index"
// key => React 内部为了进行 VNode Diff 的时候,快速找到变更的那个 Node,按需更新,性能
// key => 直接循环的是谁,就加谁上
const list = ( //换行了建议加小括号
<ul>
{/* 大括号,要写表达式了 */}
{
arr.map((item,index) => {
return(
<li key={item.id}>
<span>框架: {item.name}</span>
<span>介绍: {item.title}</span>
</li>
)
})
}
</ul>
)
// createRoot(渲染到哪儿).render(渲染谁)
createRoot(document.querySelector('#root')).render(list)
关于 key
- 特点:key 值要保证唯一,尽量避免使用索引号,key 在最终的 HTML 结构中是看不见的。
- 加在哪里:
map()
遍历谁,就把 key 加在谁上。 - 作用:React 内部用来进行性能优化时使用的,key 在最终的 HTML 结构中是看不见的。
JSX 样式处理
- 用
className
定义类名。 - 在
src
目录中准备index.css
文件,然后在index.js
文件中通过import './index.css'
引入文件。
// React 核心包
import React from 'react'
// 渲染 React 代码到页面上
import { createRoot } from 'react-dom/client'
//引入写好的 css样式
import './index.css'
// className挂上对应的类名
const warp = <div className='box'>React</div>
//渲染到页面
createRoot(document.querySelector('#root')).render(warp)
掌握 React 中使用样式的两种方式。
行内样式 - 语法
<元素 style={ {css属性1:值1,css属性2:值2} }></元素>
const warp = (
<div style={{ width: 200, height: 200, lineHeight: '200px', backgroundColor: 'black', color: 'white', textAlign: 'center', fontSize: 30 }}>React</div>
)
//渲染到页面
createRoot(document.querySelector('#root')).render(warp)
注意点
a,为啥有两个{{ }}
,外层的 {}
表示要开始写 JS 表达式了,内层的 {}
表示是一个对象。
b,属性名是小驼峰格式,例如 background-color
需要写成 backgroundColor
。
c,属性值是字符串,如果单位是 px,可以简写成数值。