diff --git a/docs/note/React.md b/docs/note/React.md
index 7d22b8e1..19633186 100644
--- a/docs/note/React.md
+++ b/docs/note/React.md
@@ -341,4 +341,695 @@ root.render()
- All in JS
- 不同于Vue的模板语法 不需要专门学习模板语法中的指令(v-for/v-if/v-bind)
+### JSX的使用
+#### 书写JSX的规范与注意事项
+
+- JSX的顶层只能有一个根元素 元素必须包裹在单独的闭合标签中
+ - 后续会接触到Fragment标签 Vue3也是将元素包裹在了Fragments标签中
+- 为了方便阅读 通常在JSX外层包裹一个小括号`()`方便阅读
+
+#### JSX的注释
+
+在JSX中编写注释,需要以`{/* ... */}`的形式,在`.jsx/.tsx`文件中,通过快捷键就可以快捷的生成注释内容
+
+本质上是通过花括号语法`{}`嵌入了一段JavaScript表达式,在表达式中书写注释
+
+```tsx{4}
+...
+return (
+
+ {/* Some Comment... */}
+
Count: {count}
+
+
+
+)
+...
+```
+
+#### JSX嵌入变量作为子元素
+
+可以通过花括号语法将变量内容嵌入到JSX语法中:
+
+```tsx
+const message = 'Hello, React!'
+const arr = ['abc', 'cba', 'nba']
+
+return (
+
+
{ message }
+
{ arr }
+
+)
+```
+
+- 变量类型为number string array类型时,可以直接展示
+- 变量类型为null undefined boolean类型时,内容为空
+ - 如果希望可以展示null/undefined/boolean类型,需要通过`.toString()`方法将其转为字符串
+ - 空字符串拼接、String构造函数等方式
+- Object对象类型不能作为子元素 (Objects are not valid as a React child)
+
+下例中,只有number类型会被正常展示,而其余变量则不会展示在视图中
+
+```tsx
+render() {
+ const number = 123
+ const n = null
+ const u = undefined
+ const b = true
+
+ return (
+
+
+ Number: {number}
+
+
+ Null: {n}
+
+
+ Undefined: {u}
+
+
+ Boolean: {b}
+
+
+ )
+}
+```
+
+将对象类型变量嵌入到JSX语法中,React会抛出错误:
+
+```tsx {6}
+...
+render() {
+ const obj = { name: 'Ziu' }
+ return (
+
+ { obj }
+
+ )
+}
+...
+```
+
+#### JSX的属性绑定
+
+- 在Vue中我们通过`v-bind`绑定属性
+- 在React中如何绑定元素属性?
+- `title` `src` `href` `class` 内联`style`等
+
+下例中,我们通过花括号语法对元素的属性进行了动态绑定,点击按钮可以切换className状态
+
+同时,动态绑定的内联样式也会发生改变,通过花括号语法动态绑定style属性
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ isActive: false,
+ title: 'Description'
+ }
+ this.changeActive = this.changeActive.bind(this)
+ }
+
+ changeActive() {
+ this.setState({
+ isActive: !this.state.isActive
+ })
+ }
+
+ render() {
+ const { isActive, title } = this.state
+ const classList = ['title', isActive ? 'active' : '']
+
+ return (
+
+
+ Hello, React!
+
+
+
+ )
+ }
+}
+```
+
+当我们通过脚手架创建项目时,可以使用第三方库来帮我们完成className的绑定
+
+- `classnames`库 `pnpm add classnames`
+- 提供了多种创建className的语法
+
+### JSX事件绑定
+
+先前的例子中,我们已经通过`onClick`给按钮绑定过事件处理函数了,其中涉及了this绑定
+
+回顾一下this的四种绑定规则:
+
+1. 默认绑定 独立执行 foo() this => undefined
+2. 隐式绑定 被一个对象执行 obj.foo() this => obj
+3. 显式绑定 call/bind/apply foo.call('aaa') this => String('aaa')
+4. new绑定 new Foo() 创建一个新对象,并且赋值给this
+
+除了之前通过`function + bind`绑定事件处理函数的方式,还可以通过箭头函数来帮我们完成处理
+
+箭头函数的内部使用this时会自动向上层作用域查找this 实际开发中这种方式并不常用
+
+```tsx {2}
+...
+changeActive = () => {
+ this.setState({
+ isActive: !this.state.isActive
+ })
+}
+...
+```
+
+相比之下更推荐使用的,是下面这种方式:
+
+```tsx {2}
+...
+
+...
+```
+
+这样书写有几种好处:
+
+- 给事件处理函数传递参数更方便
+- 书写更方便 不必主动考虑this绑定问题
+
+它的原理是,我们对外暴露的本质上是一个箭头函数,当调用箭头函数时,本质上是执行`this.changeActive`,这是 一种隐式绑定,找到的this为当前组件实例
+
+### 事件绑定参数传递
+
+- Event参数传递
+- 额外参数传递
+
+事件回调函数的第一个默认参数就是Event对象,这个Event对象是经过React包装后的,但是原生的属性都包含在内,React对其进行了一些扩展
+
+```tsx {13}
+...
+changeActive(ev) {
+ console.log('Event', ev)
+}
+
+render() {
+ return (
+
+ {/* event将作为默认入参传递给changeActive */}
+
+
+ {/* 通过箭头函数绑定事件监听回调函数时 需要手动透传一下event */}
+
+
+ )
+}
+...
+```
+
+当我们需要传递额外的参数时,通过箭头函数传递也更容易:
+
+```tsx {13}
+changeActive(ev, name, age) {
+ console.log('Event', ev)
+ console.log('Name', name)
+ console.log('Age', age)
+}
+
+render() {
+ return (
+
+ {/* NOT Recommand */}
+
+ {/* Recommand */}
+
+
+ )
+}
+```
+
+需要注意,当通过`.bind`传递额外参数时,最后一个参数才是默认传递的Event对象,这会导致非预期行为
+
+```sh
+> Event 'Ziu'
+> Name 18
+> Age {Event}
+```
+
+### JSX事件绑定案例
+
+创建一个Tab栏,选中哪个选项,哪个选项被激活切换为红色,同一时间仅有一个激活项目
+
+结合之前学习的内容,很容易就可以写出下述 代码:
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ activeIndex: 0,
+ tabList: ['Home', 'Recommend', 'Hot', 'User']
+ }
+ }
+
+ changeActive(index) {
+ this.setState({
+ activeIndex: index
+ })
+ }
+
+ render() {
+ const { activeIndex, tabList } = this.state
+
+ return (
+
+
+ {tabList.map((item, index) => (
+
+ ))}
+
+
+ )
+ }
+}
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+```
+
+### 条件渲染
+
+控制元素按照某种条件渲染,以加载状态为例
+
+列表未加载出来时,展示`加载中`,加载完毕则渲染完整内容:
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ isLoading: true
+ }
+ }
+
+ changeLoading() {
+ this.setState({
+ isLoading: !this.state.isLoading
+ })
+ }
+
+ render() {
+ const { isLoading } = this.state
+
+ return (
+
+ {isLoading ? (
+
Loading ...
+ ) : (
+
Some Content
+ )}
+
+
+ )
+ }
+}
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+```
+
+常用的条件渲染方式
+
+- `if/else/else-if`
+ - 适合判断逻辑较复杂的情况 将条件渲染抽离出来
+- 三元运算符 `?:`
+ - 适合判断逻辑简单的情况
+- 逻辑与运算符 `&&`
+ - 如果条件成立则渲染某个组件,否则什么内容都不渲染
+- 可选链 `user?.info?.name`
+
+下例中通过逻辑与运算符`&&`决定`VIP`标签是否展示在视图中
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ isVip: false
+ }
+ }
+
+ changeVip() {
+ this.setState({
+ isVip: !this.state.isVip
+ })
+ }
+
+ render() {
+ const { isVip } = this.state
+
+ return (
+
+
+ username: Ziu
+ {isVip && VIP }
+
+
+
+
+ )
+ }
+}
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+```
+
+#### 在React中简单写一个"v-show"
+
+`v-show`是Vue提供的语法糖,不同于`v-if`,它只切换元素的`display`属性。
+
+下面我们在React中简单复现一个`v-show`的效果:
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ isShow: true
+ }
+ }
+
+ changeShow() {
+ this.setState({
+ isShow: !this.state.isShow
+ })
+ }
+
+ render() {
+ const { isShow } = this.state
+
+ return (
+
+
Target Element
+
+
+ )
+ }
+}
+```
+
+实际使用中,将其封装为hooks来调用更具通用性,也更方便管理
+
+### 列表渲染中的高阶函数
+
+- `filter`函数 过滤器
+- `slice`函数 分页
+- `sorc`函数 排序
+- ...
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ stuList: [
+ { name: 'Ziu', age: 18, score: 88 },
+ { name: 'Kobe', age: 19, score: 59 },
+ { name: 'Why', age: 20, score: 61 },
+ { name: 'James', age: 21, score: 99 }
+ ]
+ }
+ }
+
+ render() {
+ const { stuList } = this.state
+
+ // 及格的学生
+ const passStuList = stuList.filter((item) => item.score >= 60)
+
+ // 分数最高的两个学生
+ const top2StuList = stuList.sort((a, b) => b.score - a.score).slice(0, 2)
+
+ return (
+
+
+ {stuList.map(({ name, age, score }) => (
+
+ {name}
+ {age}
+ {score}
+
+ ))}
+
+
+ )
+ }
+}
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+```
+
+### JSX的本质
+
+#### JSX的转换过程
+
+假设我们有下面的JSX代码:
+
+```tsx
+class App extends React.Component {
+ constructor() {
+ super()
+ }
+
+ render() {
+ const page = (
+
+
Header
+
+ Content
+
Banner
+
+ - Item 1
+ - Item 2
+ - Item 3
+ - Item 4
+ - Item 5
+
+
+
Footer
+
+ )
+ console.log(page)
+ return {page}
+ }
+}
+```
+
+通过JSX语法描述出来的template会经过Babel转化,转化为JavaScript树的数据结构
+
+在控制台中我们可以看到,子节点都存放进了父节点的`props.children`中
+
+#### 虚拟DOM树
+
+JSX仅仅是`React.createElement(component, props, ...children)`的语法糖
+
+所有的JSX语法都会被Babel转化为这样的命令式语法
+
+.createElement函数的参数
+
+- type
+ - 当前ReactElement的类型
+ - 如果是标签元素,值为字符串如:`"div"`
+ - 如果是组件元素,那么值为组件的名称
+- config
+ - 所有JSX中绑定的属性都在config中以键值对的形式存储
+ - 例如`className` => `class`
+
+我们借助Babel官网的Playground来检查一下JSX语法的转化
+
+```js
+import { jsx as _jsx } from "react/jsx-runtime";
+import { jsxs as _jsxs } from "react/jsx-runtime";
+const page = /*#__PURE__*/_jsxs("div", {
+ className: "page",
+ children: [/*#__PURE__*/_jsx("div", {
+ className: "header",
+ children: "Header"
+ }), /*#__PURE__*/_jsxs("div", {
+ className: "content",
+ children: ["Content", /*#__PURE__*/_jsx("div", {
+ className: "banner",
+ children: "Banner"
+ }), /*#__PURE__*/_jsxs("ul", {
+ children: [/*#__PURE__*/_jsx("li", {
+ children: "Item 1"
+ }), /*#__PURE__*/_jsx("li", {
+ children: "Item 2"
+ }), /*#__PURE__*/_jsx("li", {
+ children: "Item 3"
+ }), /*#__PURE__*/_jsx("li", {
+ children: "Item 4"
+ }), /*#__PURE__*/_jsx("li", {
+ children: "Item 5"
+ })]
+ })]
+ }), /*#__PURE__*/_jsx("div", {
+ className: "footer",
+ children: "Footer"
+ })]
+});
+console.log(page);
+```
+
+这时经过Babel转义后的纯JS函数,这段函数可以在浏览器中直接运行
+
+如果移除了相关JSX代码,并将他们都替换为`React.createElement`函数调用,那么得到的代码也可以直接在浏览器中运行。Babel帮助我们完成了转化,提高了开发效率,相比于通过调用`React.createElement`来描述视图,通过JSX编写的代码更加容易维护
+
+这些代码最终形成的就是虚拟DOM树,React可以将虚拟DOM渲染到页面上,形成真实DOM
+
+虚拟DOM允许React可以通过diff算法,高效地对真实DOM树进行更新
+
+### 声明式编程
+
+- 虚拟DOM帮我们从命令式编程转到了声明式编程的模式
+- 对虚拟DOM作何处理,如何渲染是由React决定的,由于做了一层抽象,那么同样可以将虚拟DOM渲染成原生组件(React Native)
+
+### 购物车案例
+
+下面写一个经典的购物车案例
+
+```tsx
+function formatPrice(price) {
+ return `$ ${price.toFixed(2)}`
+}
+
+class App extends React.Component {
+ constructor() {
+ super()
+ this.state = {
+ books: [
+ { name: 'book1', author: 'author1', price: 100, count: 0 },
+ { name: 'book2', author: 'author2', price: 200, count: 0 },
+ { name: 'book3', author: 'author3', price: 300, count: 0 },
+ { name: 'book4', author: 'author4', price: 400, count: 0 }
+ ]
+ }
+ }
+
+ changeCount(index, count) {
+ this.setState((state) => {
+ const books = [...state.books]
+ books[index].count += count
+ return { books }
+ })
+ }
+
+ removeItem(index) {
+ this.setState((state) => {
+ const books = [...state.books]
+ books.splice(index, 1)
+ return { books }
+ })
+ }
+
+ getTotal() {
+ const { books } = this.state
+ return books.reduce((acc, { price, count }) => acc + price * count, 0)
+ }
+
+ renderBookCart() {
+ const { books } = this.state
+ const total = this.getTotal()
+ return (
+
+
Shopping Cart
+
+ {books.map(({ name, author, price, count }, index) => (
+
+ {index + 1}
+ {name}
+ {author}
+ {formatPrice(price)}
+
+
+ {count}
+
+
+
+
+ ))}
+
+
+ Total: {formatPrice(total)}
+
+
+ )
+ }
+
+ renderEmptyTip() {
+ return Shopping Cart is Empty
+ }
+
+ render() {
+ const isEmpty = this.state.books.length === 0
+
+ return !isEmpty ? this.renderBookCart() : this.renderEmptyTip()
+ }
+}
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+```
+
+## React脚手架
+
+- 认识脚手架工具
+- create-react-app
+- 创建React项目
+- Webpack的配置
+
+类似于Vue提供的 `pnpm create vite` 创建一个模板,React也可以通过 `create-react-app` 来初始化一个空的React模板
+
+```sh
+pnpm add create-react-app -g # 全局安装create-react-app
+create-react-app react-app # 创建一个名为react-app的React项目
+# 删除node_modules package-lock.json
+cd react-app
+pnpm i # 使用pnpm重新安装依赖
+```
+
+```tsx
+// index.js
+import ReactDOM from 'react-dom/client'
+import App from './App'
+
+const root = ReactDOM.createRoot(document.querySelector('#root'))
+root.render()
+
+// App.js
+import React from 'react'
+
+export default class App extends React.Component {
+ render() {
+ return Hello, React!
+ }
+}
+```
\ No newline at end of file