1、创建项目
npx create-reacte-app demo
2、运行
npm run start
3、删除src下面所有文件,并新建index.js文件
import ReactDom from 'react-dom'
import App from './App.jsx'
ReactDom.render(
<App/>,
document.getElementById('root')
)
4、编写的第一个类组件
import React from "react";
let msg = '111'
class App extends React.Component{
render() {
return(
<div>
<h1>{msg}</h1>
</div>
)
}
}
export default App
5、快速创建react组件
es7+
rcc = react class component
rfc = react function component




6、示例

7、注意
1、组件文件可以是js或者jsx,不影响,但是建议组件用jsx,方法用js
2、js中出现()就代表想写html
3、js中出现{}代表想要写js
4、组件名必须要大写
5、其实export default可以写在class前面
8、动态绑定class类和写入内联样式
import React from "react";
let msg = '111'
let style = {color:'red'}
import "./app.css"
import appModule from './appModule.css'
class App1 extends React.Component{
render() {
return(
<div>
<label htmlFor="username">用户名</label> //htmlFor代表for,可以理解成label与哪个表单组件绑定
<input type="text" id="username"/>
<h1 className="box">{msg}</h1> //绑定class类
<h1 style={style}>{msg}</h1> //通过变量写入样式
<h1 style={{color:'red'}}>{msg}</h1> //{{}}代表对象中的对象,里面写入样式
</div>
)
}
}
export default App1
9、for循环(类似v-for)
let arr = ['刘备','关羽']
class App1 extends React.Component{
render() {
return(
<div>
{arr.map((item,index)=><li key={index}>{item}</li>)}
</div>
)
}
}
export default App1
10、点击事件和修改值
import React from "react";
let msg = '111'
let style = {color:'red'}
let arr = ['刘备','关羽']
class App1 extends React.Component{
state = {
num: 10
}
render() {
return(
<div>
<label htmlFor="username">用户名</label>
<input type="text" id="username"/>
<h1 className="box">{msg}</h1>
<h1 style={style}>{msg}</h1>
<h1 style={{color:'red'}}>{msg}</h1>
{arr.map((item,index)=><li key={index}>{item}</li>)}
<p>{this.state.num}</p>
<button onClick={()=>this.setState({num:this.state.num + 1})}>点击</button> //通过this.setState来修改state中的值 this.state.num获取值
</div>
)
}
}
export default App1
11、state(类似vue中的data)完整写法
class App1 extends React.Component{
constructor(props) {
super(props);
this.state = {
num:1
}
}
state = {
num: 10
}
render() {
return(
<div>
<p>{this.state.num}</p>
<button onClick={()=>this.setState({num:this.state.num + 1})}>点击</button> //通过this.setState来修改state中的值 this.state.num获取值
</div>
)
}
}
12、onclick和setState的三种写法
import React from "react";
class App1 extends React.Component{
constructor(props) {
super(props);
this.state = {
num:1
}
this.add = this.add.bind(this)
}
render() {
return(
<div>
<p>{this.state.num}</p>
<button onClick={()=>this.setState({num:this.state.num + 1})}>方法1</button>
<button onClick={this.add.bind(this)}>方法2</button>
<button onClick={()=>this.add()}>方法3</button>
<button onClick={this.add}>方法四</button>
</div>
)
}
add(){
this.setState({num:this.state.num + 1})
}
}
export default App1
13、函数式组件
import React from 'react';
function App1(props) {
return (
<div></div>
);
}
export default App1;
14、hooks
1、钩子 理解的意思大概就是类似vue中的生命周期
2、分两种:react官方提供的hook、开发人员自定义的hook
14-1 官方提供的hook,通过hook改变值(useState)

14-2 官方提供的hook,通过hook请求数据(useEffect),类似vue中的mounted、updated、beforeDestro
useEffect就是react中mounted、updated、beforeDestroy的结合体
import {useState,useEffect} from "react";
function App2(props) {
let [mag,setMsg] = useState(1)
useEffect(()=>{
return ()=>{
console.log('销毁阶段')
}
})
return (
<div>
<h1 onClick={()=>setMsg(1)}>{mag}</h1>
{/*实现累加*/}
<h1 onClick={()=>setMsg(mag++)}>{mag}</h1>
</div>
);
}
export default App2;
15、父传子(props)
import React from 'react';
function Child(props) {
return (
<div>
//子组件接收父组件的值 props
<h1>{props.num}</h1>
</div>
);
}
function App3(props) {
return (
<div>
<Child num={1}/>
</div>
);
}
export default App3;
16、子传父
import React,{useState}from 'react';
function Child(props) {
return (
<div>
<h1>{props.num}</h1>
<button onClick={()=>props.changeNumFn()}>子传父</button>
</div>
);
}
function App3(props) {
let [num,serNum] = useState(1)
return (
<div>
<Child num={num} changeNumFn={()=>serNum(num+1)}/>
</div>
);
}
export default App3;
17、跨组件传值(createContext)适用于父向孙子传值
17-1完整版写法繁琐,不推荐)
import React,{useState,createContext}from 'react';
const NumContext = createContext();
function Child() {
return (
<NumContext.Consumer>
{
({num,setNum})=>(
<div>
<h2>{num}</h2>
<button onClick={()=>setNum(num+1)}>点击改变</button>
</div>
)
}
</NumContext.Consumer>
);
}
const Father = ()=><Child/>
function App3(props) {
let [num,setNum] = useState(2)
return (
<NumContext.Provider value={{num,setNum}}>
<Father></Father>
</NumContext.Provider>
);
}
export default App3;
17-2 简写,通过useContext来获取num,setNum的值(推荐)
import React,{useState,createContext,useContext}from 'react';
const NumContext = createContext();
function Child() {
let {num,setNum} = useContext(NumContext)
return (
<div>
<h2>{num}</h2>
<button onClick={()=>setNum(num+1)}>点击改变</button>
</div>
);
}
const Father = ()=><Child/>
function App3(props) {
let [num,setNum] = useState(2)
return (
<NumContext.Provider value={{num,setNum}}>
<Father></Father>
</NumContext.Provider>
);
}
export default App3;
18、受控组件(类似vue中的v-model)
import React,{useState}from 'react';
function App3(props) {
let [value,setValue] = useState(2)
return (
<>
<input value={value} onChange={(e)=>setValue(e.target.value)}/>
<button onClick={()=>console.log(value)}></button>
</>
);
}
export default App3;
19、不受控组件(useRef)类似vue中的ref
import React,{useState,useRef}from 'react';
function App3(props) {
let dom = useRef(null)
return (
<>
<input type="text" ref={dom}/>
<button onClick={()=>console.log(dom.current.value)}>不受控组件 </button>
</>
);
}
export default App3;
20、memo(当父组件更新本身数据,但是与子组件毫无干系,可还是强制刷新了子组件数据,用memo来避免)只适用于静态值,不推荐
import React,{useState,memo}from 'react';
const Child = memo(()=>{
console.log('我被负组件更新了')
return <div></div>
})
function App5(props) {
const [num,setNum] = useState(123)
return (
<div>
<h1>{num}</h1>
<button onClick={()=>setNum(123)}></button>
<Child></Child>
</div>
);
}
export default App5;
21、解决方案(useCallback)(useCallback必须配合memo使用,且只用于点击事件)
import React,{useState,memo,useCallback}from 'react';
const Child = memo((props)=>{
console.log('我被负组件更新了')
return <div onClick={()=>props.dSth()}></div>
})
function App5(props) {
const [num,setNum] = useState(123)
const dSth = useCallback(()=>setNum((num)=>num + 1),[])
return (
<div>
<h1>{num}</h1>
<button onClick={()=>setNum(123)}></button>
<Child dSth={dSth}></Child>
</div>
);
}
export default App5;
22、可替代useCallback方案(useMemo),简写更实用(类似vue中的计算属性)
import React,{useState,memo,useMemo}from 'react';
const Child = memo((props)=>{
console.log('我被负组件更新了')
return <div onClick={()=>props.dSth()}></div>
})
function App5(props) {
const [num,setNum] = useState(123)
const dSth = useMemo(()=>{
return ()=>setNum(num + 1)
},[])
return (
<div>
<h1>{num}</h1>
<button onClick={()=>setNum(123)}></button>
<Child dSth={dSth}></Child>
</div>
);
}
export default App5;
23、react-redux(类似vue中的vuex)
1、 安装
npm i redux react-redux
2、 创建文件夹store,并在下方创建index和reducer文件
npm i redux react-redux

3、编写文件reducer.js文件
const defaultState = {
num:1
}
export default (state = defaultState)=>{
return state
}
4、编写index.js
import reducer from "./reducer";
import {createStore} from 'redux'
const store = createStore(reducer)
export default store
5、使用和获取redux的值
1、在index.js文件中引入,类似main.js
import ReactDom from 'react-dom'
import App6 from './App6.jsx'
import {Provider} from 'react-redux'
import store from './store'
ReactDom.render(
<Provider store={store}>
<App6/>
</Provider>,
document.getElementById('root')
)
2、再到对应文件组件中引入---获取值
import React from 'react';
import {connect} from "react-redux";
function App6(props) {
return (
<div>{props.num}</div>
);
}
const mapStateToProps = (state)=>{
return {
num:state.num
}
}
export default connect(mapStateToProps)(App6);
3、事件派发,类似vue中的vuex调用事件并修改值
import React from 'react';
import {connect} from "react-redux";
function App6(props) {
return (
<div>
{props.num}
<button onClick={()=>props.leijia()}>累计</button>
</div>
);
}
const mapStateToProps = (state)=>{
return {
num:state.num
}
}
const mapDispatchToProps = (dispatch) =>{
return{
leijia(){
const action = {type:"addNum"}
dispatch(action)
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(App6);
const defaultState = {
num:1
}
export default (state = defaultState,action)=>{
let newState = JSON.parse(JSON.stringify(state))
if(action.type === 'addNum'){
newState.num++
}
return newState
}
24、路由
1、安装
npm install react-router-dom@版本
2、创建router文件夹,并创建index.jsx文件
import App from '../App'
import Home from '../pages/home'
import {BrowserRouter,Routes,Route} from "react-router-dom";
const BaseRouter = ()=>(
<BrowserRouter>
<Routes>
<Route path="/" element={<App></App>}>
<Route path="/home" element={<Home></Home>}></Route>
</Route>
</Routes>
</BrowserRouter>
)
export default BaseRouter
3、入口文件引入
import ReactDom from 'react-dom'
import Router from './router/index.jsx'
import {Provider} from 'react-redux'
import store from './store'
ReactDom.render(
<Provider store={store}>
<Router/>
</Provider>,
document.getElementById('root')
)
4、主视口文件引入(Outlet)类似vue中的router-view
import React from "react";
import {Outlet} from "react-router-dom";
class App extends React.Component{
render() {
return(
<div>
<Outlet></Outlet>
</div>
)
}
}
export default App

5、跳转(Link(类似vue中的vue-router),useNavigate(类似vue中的this.$router))
import React from "react";
import {Outlet,Link,useNavigate} from "react-router-dom";
class App extends React.Component{
render() {
console.log(123)
const navicgate = useNavigate()
const useNavigateBtn = ()=>{
navicgate('/home')
}
return(
<div>
<p>
<Link to="/home">跳转到首页</Link>
<button onClick={useNavigateBtn}>跳转到首页</button>
</p>
<Outlet></Outlet>
</div>
)
}
}
export default App
6、获取整个路由列表或者路径(useLocation),类似vue中的this.$route.path
import React from "react";
import {Outlet,Link,useLocation} from "react-router-dom";
function App(props) {
const location = useLocation()
console.log(location)
return (
<div>
<Link to="/home">跳转到首页</Link>
<Outlet></Outlet>
</div>
);
}
export default App;

6、跳转携带参数
1、方案1 在路径后面携带,获取参数(useParams)
import React from 'react';
import {useParams} from "react-router-dom";
function Home(props) {
let {id} = useParams()
console.log(id)
return (
<div>123123</div>
);
}
export default Home;



2、方案2问号的形式/home?id=123
import React from 'react';
import {useSearchParams} from "react-router-dom";
function Home(props) {
const [searchParams] = useSearchParams()
let id = searchParams.getAll('id')[0]
return (
<div>123123</div>
);
}
export default Home;
3、事件跳转携带参数,可携带多个参数和对象
navicgate('/home',{
state:{
username:'张三'
}
})
取出
let Location = useLocation()
console.log(Location.state.username)
4、404设置
{}
{}
注意:在页面中引入图片路径只能用impotr 不能使用绝对路径