1. 起步
# 创建项目
npx create-react-app project-name
Vscode - React插件安装
添加该依赖后:
rcc 和 rfc可以创建组件的方法
# 快速启动的代码块
rcc - react class component
rfc - react fucntion component
1.1 Hello world
// index.js
import react from 'react'
import ReactDOM from 'react-dom'
import App from './App.jsx'
ReactDOM.render(
<App />
, document.getElementById('root')
)
// App.js
import React from 'react'
import ReactDom from 'react-dom'
class App extends React.Component {
render() {
return (
<ul>
<li>hello world</li>
<li>hello world</li>
</ul>
)
}
}
export default App
1.2 JSX
JSX是JavaScript xml,语法上与html有些区别。
class改成className, for改成htmlFor…
所有的使用js语法的地方,都是大括号。
绑定样式
style={{ backgroundColor: 'red' }}
// 第一层{}代表要使用js语法,第二层表明这是一个object
// 由于里面是JavaScript语法,所以需要写成驼峰命名法
1.2.1 for循环产生元素
const arr = ['刘备', '关羽', '张飞']
render(){
return (
<div>
{
arr.map((item, index) => {
return <li key={index}>{item}</li>
})
}
</div>
)
}
// 特别备注:只有map有返回值,forEact返回值是undefined, 所以这里不能用forEach
1.3 React下绑定点击事件
import React, { Component } from 'react'
export default class App2 extends Component {
state = {
num: 1
}
render() {
return (
<div>
num : {this.state.num}
<br />
{/* state */}
<button onClick={() => this.setState({ num: this.state.num + 1 })}>累加</button>
{/* 箭头函数不改变this的指向 */}
<button onClick={() => this.addNum()}>累加</button>
{/* 修改this的指向 */}
<button onClick={this.addNum.bind(this)}>累加</button>
</div>
)
}
addNum() {
this.setState({ num: this.state.num + 1 })
}
}
2. 函数式编程
2.1 函数式版本的累加器
import React, { useState } from 'react'
// 函数式编程
export default function App3() {
const [num, setNum] = useState(1);
function add() {
setNum(num + 1)
}
return (
<div>
<span>{num}</span>
<br />
<button onClick={add}>累加</button>
</div >
)
}
备注:所有以use开头的useXXX,都是Hook
2.2 useState
useState<number>(initialState: number | (() => number)): [number, React.Dispatch<React.SetStateAction<number>>]
2.3 useEffect
使用useEffect可以模拟Vue中的生命周期函数
// 模拟mouted
useEffect(() => {
console.log('hello')
})
// 监控数据更新(模拟updated)
useEffect(() => {
console.log('发生了改变')
}, [num])
// 第二个参数为 [], 意味着什么也不监控
// 第二个参数为 [num1,num2]
// 模拟beforeDestory
useEffect(() => {
return () => {
console.log('销毁阶段,该代码会执行')
}
}, [num])
2.4 使用memo缓存组件
import React, { useState, memo } from 'react'
const Child = memo(() => {
console.log('子组件更新 :>> ');
return (
<h2>子组件</h2>
)
})
3. 参数传递
3.1 父传子
function Father(props) {
return (
<>
<h1>Father</h1>
<span > num={props.num} </span>
</>
)
}
export default function App4() {
return (
<div>
<Father num={2} />
</div>
)
}
// 备注:可通过属性将方法传递给子组件,实现修改父组件中的数据
3.2 context跨级组件传参
import React, { createContext } from 'react'
// 注册上传文环境
const Context = createContext()
function Child() {
return (
// 消费者组件
<Context.Consumer>
{
(data) => {
console.log('data :>> ', data);
return (
<span>
{JSON.stringify(data)}
</span>
)
}
}
</Context.Consumer>
)
}
export default function App5() {
return (
// 提供者组件
<Context.Provider value={{
currUser: { name: 'jack' }
}}>
<Child></Child>
</Context.Provider >
)
}
3.3 实现v-model
// 实现v-model
export default function App7() {
const [val, setVal] = useState('初始值')
return (
<div>
<input type="text" value={val} onChange={(e) => setVal(e.target.value)} />
<button onClick={() => console.log('val', val)}>获取当前的值</button>
</div>
)
}
4. react redux
4.1 安装依赖
npm i redux react-redux
4.2 基础示例
store/index.js
import { createStore } from "redux"
import reducer from "./reducer"
const store = createStore(reducer)
export default store
store/reducer.js
const defaultState = {
num: 100
}
export default (state = defaultState) => state
index.js
import { Provider } from "react-redux";
import store from './store'
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
// 添加数据提供者
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>
);
connect映射值
import React from 'react'
import { connect } from 'react-redux'
function App9(props) {
// 通过props拿到全局store中的值
return (
<h1>
{props.num}
</h1>
)
}
const mapStateToProps = (state) => {
return {
num: state.num
}
}
// 使用连接器, 映射值
export default connect(mapStateToProps)(App9)
4.3 调用函数和传递参数
reducer.js
const defaultState = {
num: 1
}
export default function (state = defaultState, action) {
const newState = JSON.parse(JSON.stringify(state))
// action值传递
switch (action.type) {
case 'addNum':
console.log('action :>> ', action);
newState.num += (action.value)
break
default:
break
}
return newState
}
import React from 'react'
import { connect } from 'react-redux'
function App9(props) {
return (
<>
<h1>
{props.num}
</h1>
<button onClick={props.addNum}>增加</button>
</>
)
}
const mapStateToProps = (state) => {
return {
num: state.num
}
}
const mapDispathToProps = (dispatch) => {
return {
addNum() {
// 触发action函数(可以传任意个参数,最终都会在action对象中)
dispatch({ type: 'addNum', value: 2, randomValue: 999 })
}
}
}
// 使用连接器, 映射值
export default connect(mapStateToProps, mapDispathToProps)(App9)
5. react router
5.1 安装依赖
npm install react-router-dom@6
5.2 配置router
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import App from '../App10'
import About from '../pages/About'
import Home from '../pages/Home'
const BaseRouter = () => {
return (
<BrowserRouter>
<Routes>
// path代表匹配路径 , element代表渲染的元素
<Route path="/" element={<App />}>
<Route path="/home" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Route>
</Routes>
</BrowserRouter>
)
}
export default BaseRouter
在index.js中引入router
在需要使用的地方,配置<Outlet>
,类似vue-router中的router-view。
用于渲染匹配的路由对应的文件内容。
import { Outlet } from 'react-router-dom'
export default function App10() {
return (
<div>
<h1>
App10
</h1>
<Outlet />
</div>
)
}
5.3 Link标签
类似于router-link,最终会被渲染成a标签
<ul>
<li> <Link to='/home'>首页</Link> </li> // 实现界面跳转
<li> <Link to='/about'>关于</Link> </li>
</ul>
5.4 useLocation
用于访问当前路径
const location = useLocation()
function handleClick() {
console.log('location :>> ', location);
}
5.5 路径参数
<Route path="/home" element={<Home />}>
<Route path=':id' element={<></>}></Route> // 参数匹配
</Route>
const params = useParams() // 获取参数
console.log('params :>> ', params);
5.6 搜索参数(?id=1)
const [searchParams] = useSearchParams()
console.log('id :>> ', searchParams.getAll('id')); // 匹配所有的,返回数组
console.log('id :>> ', searchParams.get('id')); // 只匹配第一个
for (let key of searchParams.keys()) {
console.log('key :>> ', key);
}
5.7 事件跳转携带参数(携带大量数据)
const navigate = useNavigate()
navigate("/home", {
state: [{ name: 'zhangsan' }, { name: 'lisi' }]
})
接收数据会在location中的state里
const location = useLocation()
5.8 匹配404界面
// 用于匹配404界面
<Route path="*" element={<Error />}></Route>