[React Docs Beta (jscn.org)](https://beta.react.jscn.org/)
# 安装浏览器扩展
用Chrome的去极简插件下载。
React创建项目有多种方式
- 传统方式使用 create-react-app
- 也可以使用vite
create-react-app
```Bash
npx create-react-app my-app
```
vite
```Bash
npm create vite@latest 项目名 -- --template react
```
或者直接
```Bash
npm create vite # 剩下的自己选择
```
# React组件
react组件分为两种组件,一种叫类组件,一种叫函数式组件,函数式组件速度更快,性能更好,但是有先天的缺陷,最开始react开发,使用的类组件+函数式组件的开发方式。在React16.8之后推出hooks,弥补了函数式组件的缺陷,所以新的开发方式变成了函数式组件+hooks的开发方式。这个东西就像Vue2到Vue3转变一样。
# JSX
是一个 JavaScript 的语法扩展。我们建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言,但它具有 JavaScript 的全部功能。
可以借助Vue对JSX的介绍了解和vue模板的区别
[渲染函数 & JSX | Vue.js (vuejs.org)](https://cn.vuejs.org/guide/extras/render-function.html#jsx-tsx)
```JavaScript
h('div', {
id: "box",
className: "container"
}, "内容")
```
转换为JSX
```React JSX
<div id="box" className="container">内容</div>
```
这个不是一个字符串,也不是html标签,这个语法叫jsx
h('div', {}, [
h('span', '内容'),
h('span', '内容'),
h('span', '内容')
])
```React JSX
(
<div>
<span>内容</span>
<span>内容</span>
<span>内容</span>
</div>
)
```
## 插值
如果想要插值,使用 `{}` 变量需要在当前函数中
```JavaScript
function App () {
let msg = "Hello React"
return (
<div>{msg}</div>
)
}
```
虽然这种方式可以插值,但是如果我们想要值能够被更改,就需要使用第一个hook`useState`
```React JSX
import { useState } from 'react'
function App () {
let [msg] = useState("Hello React")
return (
<div>{msg}</div>
)
}
```
useState就像是Vue3中的ref,用来声明一个具有数据响应式的变量。只不过useState返回的是一个数组,这个数组的两个值分别是
1. 初始值
2. 设置这个值的函数
## 列表渲染
如果我们有一个数组,我们想要渲染成一个列表,需要借助`map`生成一个jsx数组,例如
```text
[1, 2, 3] 需要转换成 [<li>1</li>, <li>2</li>, <li>3</li>]
```
```React JSX
function App() {
let stus = ["张三", "李四", "王五"]
return (
<div>
<h1>学生列表</h1>
<ul>
{
stus.map((stu, index) => <li key={index}>{stu}</li>)
}
</ul>
</div>
)
}
export default App;
```
如果是复杂的数据呢???假如我们的数组中包含的是对象
```JavaScript
let stus = [
{
name: "张三",
age: 18,
sex: "男"
},
{
name: "李四",
age: 20,
sex: "男"
},
{
name: "王五",
age: 18,
sex: "男"
}
]
```
```React JSX
function App() {
let stus = [
{
name: "张三",
age: 18,
sex: "男"
},
{
name: "李四",
age: 20,
sex: "男"
},
{
name: "王五",
age: 18,
sex: "男"
}
]
return (
<div>
<h1>学生列表</h1>
<ul>
{
stus.map((stu, index) =>
(
<li key={index}>
<span>{stu.name}</span>
<span>{stu.age}</span>
<span>{stu.sex}</span>
</li>
)
)
}
</ul>
</div>
)
}
export default App;
```
## 条件渲染
jsx中不支持if else操作,但是支持三元运算,所以可以在对应的位置上展示相关的操作
```React JSX
function App() {
let status = true
return (
<div>
{
status ? <div>status为true时显示</div> : <div>status为false时显示</div>
}
</div>
)
}
export default App;
```
如果组件只是需要返回一个简单的结构,我们可以使用return操作来解决问题
```React JSX
function App() {
let status = false
if (status) {
return <div>status为true时显示</div>
}
return <div>status为false时显示</div>
}
export default App;
```
## 事件
react的事件绑定很好理解
```React JSX
<标签 on事件类型={函数体}>
```
比如我们要触发一个点击事件
```JavaScript
function App (){
let clickHandler = () => {}
return (
<button onClick={clickHandler}></button>
)
}
```
如果我们需要给事件函数中传递参数,那么需要在函数体外包裹箭头函数
```React JSX
function App (){
let clickHandler = (num) => {}
return (
<button onClick={() => clickHandler(2)}></button>
)
}
```
建议大家养成习惯,传不传参都放在箭头函数中
```React JSX
<标签 on事件类型={() => 要调用的函数()}>
```
在React事件中,如何传递事件对象
```text
let 事件函数 = (形参1, 形参2, 事件对象形参) => {}
<button onClick={(e) => 事件函数(参数1, 参数2, e)}>
```
如果需要获取到我们输入框中的值,可以使用`e.target.value`
```React JSX
<input type="text" onChange={(e) => console.log(e.target.value)}/>
```
## 绑定动态属性
如果想要在标签上的属性中绑定动态值
```React JSX
let 变量名 = "值"
<标签 属性名={变量名}>
```
如果要去设置样式,我们在jsx中必须以下方的写法去定义样式
```JavaScript
<标签 style={{属性名: 属性值, 属性名2: 属性2}}>
```
两个大括号并非双大括号写法,而是一个大括号中包了一个对象。在这个对象中,我们可以直接使用动态值
```React JSX
let color = "blue"
<标签 style={{属性名: 属性值, 属性名2: 属性2, color: color}}>
```
如果是动态设置class,react中不支持向vue一样`:class="['box1', boxname, {active: isActive}]"`的写法,如果我们想要实现这种写法,需要借助`classnames`库
```Bash
npm i classnames
```
```React JSX
import classnames from 'classnames';
// 用法和vue的class绑定类似
let btnClassName = "btn4" // 表示可以直接被修改的变量
<button className={classnames('btn', 'btn2', 'btn3', btnClassName, {'btnactive': false})}>按钮</button>
```
# 组件
React的组件和Vue的思想一样,只不过结构不同,React组件是一个函数
```React JSX
function 组件函数名() {
return (
<div></div>
)
}
export default 组件函数名
```
如果想要使用组件
```JavaScript
import 组件名 from 'path'
<div>
<组件名></组件名>
</div>
```
## props
React中如何获取到组件标签上的属性值
```React JSX
<组件标签 属性名="属性值"></组件标签>
```
在子组件中
```React JSX
function 子组件(props) {
return (
<div>
{props.属性名}
</div>
)
}
```
我们也可以直接解构
```React JSX
function 子组件({属性名}) {
return (
<div>
{属性名}
</div>
)
}
```
注意!!!!!props中有一个关键的属性名为children,这个表示,我们直接写在组件标签中的内容,就是我们的vue中的slot
```React JSX
<子组件标签>内容</子组件标签>
```
在子组件中
```React JSX
function 子组件(props) {
return (
<div>
{props.children}
</div>
)
}
```
也可以直接解构
```React JSX
function 子组件({children}) {
return (
<div>
{children}
</div>
)
}
```
封装一个房子组件,组件中包含了一个卧室组件,一个卫生间组件,卧室组件中包含一个床组件,床上有个dog组件
```text
房子
卧室
床
狗
卫生间
```
## 状态提升
本该在组件Child的状态,因为有其他组件需要使用,我们就需要把这个状态提升到共同祖先组件上
在React不存在向vue一样的通信方式,数据的传递从父组件到子组件都是通过props。但是从子组件到父组件,两者的思想不同
- Vue 父组件需要什么值,在子组件通过调用emit传递过去,父组件创建好接收的函数,绑定对应的自定义事件即可。
- React 父组件需要什么值或者什么操作,父组件准备好修改这个值方法,然后通过props将方法传递给子组件,子组件调用即可。
```Vue
// Child.vue
<template>
<button @click="clickHandler">点击传递一个1到父元素</button>
</template>
<script setup>
let clickHandler = () => {
emit('自定义事件', 1)
}
</script>
```
```Vue
// Parent.vue
<template>
<Child @自定义事件="getNumber"></Child>
</template>
<script setup>
let getNumber = (num) => {
// num就是1
}
</script>
```
React
```React JSX
let Child = ({父组件传来的函数}) => {
return (
<button onClick={() => 父组件传来的函数(1)}>点击传递一个1到父元素</button>
)
}
let Parent = () => {
let getNumber= (num) => {
console.log(num)
}
return (
<Child 父组件传来的函数={getNumber}></Child>
)
}
```
如果子组件在封装时,想要实现某个功能,我们就可以去触发一个函数,但是触发前需要确定函数是否存在
```React JSX
函数名 && 函数名()
<button
disabled={disabled}
className={className}
onClick={(e) => {
e.stopPropagation()
onClick && onClick(e) // 别人用我的组件时,可以给我传递一个名字为onClick的属性,属性值是一个函数
}}
>
{children}
</button>
```