方法一:使用npm安装react脚手架
npm install -g create-react-app,然后create-react-app app-name方法二:直接使用react脚手架搭建项目结构
npx create-react-app app-name,其中app-name的“-”不能省略,npx是临时安装脚手架,构建完项目后会自动删除。

package.json
{
//项目依赖目录
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
//命令列表
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
}
index.js
//React:框架的核心包
//ReactDOM:专门做渲染相关的包
import React from 'react';
import ReactDOM from 'react-dom/client';
//引入全局的样式文件
import './index.css'
//项目的根组件
import App from './App';
//获取root元素,root元素位于public目录下index.html中
const root = ReactDOM.createRoot(document.getElementById('root'));
//对root进行渲染
root.render(
//如果是react18版本需要去掉标签
<React.StrictMode>
<App />
</React.StrictMode>
);
概念:JSX是JavaScript XML (HTML)的缩写,表示在JS代码中书写HTML结构
作用:在React中创建HTML结构(页面UI结构)
原理:JSX并不是标准的JS语法,是JS的语法扩展,浏览器默认是不识别的,脚手架中内置的@babel/plugin-transform-react-jsx包,用来解析该语法
语法:
{JS表达式}//将此式放入html语法中即可,注意只能是表达式不能是语句(如if等语句则报错)
const name = '佳佳'
const flag = true
function App() {
return (
<div className="App">
{name}
{flag?'周周':'蛇蛇'}
</div>
);
}
export default App;

const songs = [
{ id: 1, name: '痴心绝对' },
{ id: 2, name: '像我这样的人' },
{ id: 3, name: '南山南' }
]
function App() {
return (
<div className="App">
//使用map进行逐个渲染
{songs.map(itemName => <li key={songs.id}>{itemName.name}</li>)}
//等价于
<li key={songs[0].id}>{songs[0].name}</li>
<li key={songs[1].id}>{songs[1].name}</li>
<li key={songs[2].id}>{songs[2].name}</li>
</div>
);
}
export default App;
// 来个布尔值
const flag = true
function App() {
return (
<div className="App">
{/* 条件渲染字符串 */}
{flag ? 'react真有趣' : 'vue真有趣'}
{/* 条件渲染标签/组件 */}
{flag ? <span>this is span</span> : null}
</div>
)
}
export default App
const fun = (type)=>{
if (type === 1)return <h1>蛇蛇</h1>
else return <h1>周周</h1>
}
function App() {
return (
<div className="App">
{fun(1)}
</div>
);
}
export default App;
const styleObj = {
color:red
}
function App() {
return (
<div className="App">
<div style={ styleObj }>this is a div</div>
</div>
)
}
export default App
创建一个css文件,然后在本文件导入即可使用css中已声明好的样式
app.css
.title {
font-size: 30px;
color: blue;
}
app.js
import './app.css'
function App() {
return (
<div className="App">
<div className='title'>this is a div</div>
</div>
)
}
export default App
function App() {
//e是点击事件信息
const onclickEvent=(e,str)=>{
console.log(e,str)
}
return (
<div className="App" onClick={(e)=>{onclickEvent(e,"蛇蛇")}}>
点击一下
</div>
);
}
export default App;
组件是独立且封闭的单元,默认情况下组件只能使用自己的数据(state)
组件化开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据
为了能让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信
父传子:
1. props是只读对象(readonly)
根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改
2. props可以传递任意数据
数字、字符串、布尔值、数组、对象、函数、JSX
import React from 'react'
// 函数式子组件
function FSon(props) {
console.log(props)
return (
<div>
子组件1
{props.msg}
</div>
)
}
// 父组件
class App extends React.Component {
state = {
message: 'this is message'
}
render() {
return (
<div>
<div>父组件</div>
<FSon msg={this.state.message} />
</div>
)
}
}
export default App
子传父:
子组件调用父组件的函数进行传值;
import React from 'react'
// 子组件
function Son(props) {
function handleClick() {
// 调用父组件传递过来的回调函数 并注入参数
props.changeMsg('this is newMessage')
}
return (
<div>
<button onClick={handleClick}>change</button>
</div>
)
}
class App extends React.Component {
state = {
message: 'this is message'
}
// 提供回调函数
changeMessage = (newMsg) => {
console.log('子组件传过来的数据:',newMsg)
this.setState({
message: newMsg
})
}
render() {
return (
<div>
<Son
msg={this.state.message}
// 传递给子组件
changeMsg={this.changeMessage}
/>
</div>
)
}
}
export default App
| 钩子 函数 | 触发时机 | 作用 |
|---|---|---|
| constructor | 创建组件时,最先执行,初始化的时候只执行一次 | 1. 初始化state 2. 创建 Ref 3. 使用 bind 解决 this 指向问题等 |
| render | 每次组件渲染都会触发 | 只用于渲染UI(注意: 不能在里面调用setState() ) (与 挂载阶段 是同一个render) |
| componentDidMount | 组件挂载(完成DOM渲染)后执行,初始化的时候执行一次 | 1. 发送网络请求 2.DOM操作 |
| 钩子函数 | 触发时机 | 作用 |
|---|---|---|
| render | 每次组件渲染都会触发 | 只用于渲染UI(与 挂载阶段 是同一个render) |
| componentDidUpdate | 组件更新后(DOM渲染完毕) | DOM操作,可以获取到更新后的DOM内容,不要直接调用setState |
Hooks的出现解决了俩个问题 1. 组件的状态逻辑复用 2.class组件自身的问题
使用步骤
useState 函数useState 函数,并传入状态的初始值useState函数的返回值中,拿到状态和修改状态的方法import { useState } from 'react'
function App() {
// 参数:状态初始值比如,传入 0 表示该状态的初始值为 0
// 返回值:数组,包含两个值:1 状态值(state) 2 修改该状态的函数(setState),名字可以自定义
const [count, setCount] = useState(0)
return (
<button onClick={() => { setCount(count + 1) }}>{count}</button>
)
}
export default App
useState(0) 将传入的参数作为状态初始值,即:0setCount(count + 1) 修改状态,因为状态发生改变,所以,该组件会重新渲染useState(0),此时 React 内部会拿到最新的状态值而非初始值,比如,该案例中最新的状态值为 11、什么是副作用
副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,主作用就是根据数据(state/props)渲染 UI,除此之外都是副作用(比如,手动修改 DOM)
常见的副作用
- 数据请求 ajax发送
- 手动修改dom
- localstorage操作
useEffect函数的作用就是为react函数组件提供副作用处理的!
2、监听变量变化
useEffect注意事项(useEffect是在dom渲染之后才执行的)
不加依赖项:初始化+重新渲染
加[]:初始化执行一次
加特定的依赖项[count , name]就会监听这两种属性
function App() {
const [count, setCount] = useState(0)
const [name, setName] = useState('str')
useEffect(() => {
console.log('副作用执行了')
}, [count],[name])
return (
<>
<button onClick={() => { setCount(count + 1) }}>{count}</button>
<button onClick={() => { setName('cp') }}>{name}</button>
</>
)
}
3、在函数组件销毁的时候清除副作用
import { useEffect, useState } from "react"
function Test(){
useEffect(() => {
const timerId = setInterval(() => {
console.log("1s打印一次")
}, 1000)
return () => {
// 用来清理副作用的事情,当App组件被销毁的时候
clearInterval(timerId)
}
})
return (
<div>
{'test'}
</div>
)
}
const App = () => {
const [flag, setFlag] = useState(true)
return (
<div>
{flag?<Test/>:null}//点击按钮之后,flag变false,组件Test销毁
<button onClick={() => setFlag(!flag)}>swicth</button>
</div>
)
}
export default App
使用场景
在函数组件中获取真实的dom元素对象或者是类组件对象
使用步骤
useRef 函数useRef 函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(组件实例)import { useEffect, useRef } from 'react'
function App() {
const h1Ref = useRef(null)
useEffect(() => {
console.log(h1Ref)
},[])
return (
<div>
<h1 ref={ h1Ref }>this is h1</h1>
</div>
)
}
export default App
作用:将父组件的值可以直接传给孙子组件
import { createContext, useContext } from 'react'
// 创建Context对象
const Context = createContext()
function Foo() {
return <div>Foo <Bar/></div>
}
function Bar() {
// 底层组件通过useContext函数获取数据
const name = useContext(Context)
return <div>Bar {name}</div>
}
function App() {
return (
// 顶层组件通过Provider 提供数据
<Context.Provider value={'this is name'}>
<div><Foo/></div>
</Context.Provider>
)
}
export default App