尚硅谷React教程
尚硅谷React教程(已加更新版内容,B站最火)
https://www.bilibili.com/video/BV1wy4y1D7JT
P1 001_尚硅谷react教程_react简介
react-router
pubsub 怕沙
redux 绿丢
ant-design 安的塞
1.原生JavaScript操作DOM繁琐、效率低(DOM-API操作UI)。
2.使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排。
3,原生JavaScript没有组件化编码方案,代码复用率低。
React的特点
1.采用组件化模式、声明式编码,提高开发效率及组件复用率。
2.在React Native中可以使用React语法进行移动端开发。
3,使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互。
学习React之前你要掌握的JavaScript基础知识
判断this的指向
class(类)
ES6语法规范
npm包管理器
原型、原型链
数组常用方法
模块化
英文官网:https://reactjs.org/
中文官网:https://react.docschina.org/
react developer tools 4.9.0 component 组件 profiler性能
美团 react写的
P2 002_尚硅谷react教程_hello_react案例
P3 003_尚硅谷react教程_虚拟DOM的两种创建方式
P4 004_尚硅谷react教程_虚拟DOM与真实DOM
P5 005_尚硅谷react教程_jsx语法规则
P6 006_尚硅谷react教程jsx小练习
P7 007_尚硅谷react教程_组件与模块
P8 008_尚硅谷react教程_开发者工具的安装
P9 009_尚硅谷react教程_函数式组件
P10 010_尚硅谷react教程_复习类相关知识
函数式组件 类式组件:
旧版16.8
P11 011-尚硅谷react教程-类式组件
P12 012-尚硅谷react教程-对state的理解
P13 013-尚硅谷react教程-初始化state
P14 014_尚硅谷react教程_react中的事件绑定
P15 015-尚硅谷react教程_类中方法中的this
P16 016-尚硅谷react教程-解决类中this指向问题
P17 017-尚硅谷react教程-setState的使用
P18 018-尚硅谷react教程-state的简写方式
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Item extends Component {
state = { }
constructor(props){
super(props)
// 一:
// this.handleClick=this.handleClick.bind(this) //不在标签绑定this 这性能好
}
shouldComponentUpdate(nextProps,nextState){
//性能优化
if(nextProps.content!==this.props.content){
return true
}else{
return false
}
}
render() {
return (
<li onClick={this.handleClick}>{this.props.avname}-{this.props.content}</li>
);
}
//一:
// handleClick(){
// this.props.deleteItem(this.props.index)
// }
//二:
handleClick=()=>{
this.props.deleteItem(this.props.index)
}
}
Item.propTypes={
content:PropTypes.string.isRequired,
index:PropTypes.number,
deleteItem:PropTypes.func
}
Item.defaultProps={
avname:'koo'
}
export default Item;
P19 019-尚硅谷react教程_总结state
P20 020-尚硅谷react教程-props的基本使用
我是用类定义的组件(适用于【复杂组件】的定义)有state
我是用函数定义的组件(适用于1简单组件】的定义)无state
hooks 候s
onClick={this.demo()} 立即调用 去掉()才点击生效
P21 021_尚硅谷react教程_批量传递props
let obj={name:'koo',age:18}
<Person {...obj}/>
P22 022-尚硅谷react教程_对props进行限制_
低版本 propTypes内置15.x 16.x需要引入
P23 023_尚硅谷react教程_props的简写方式
P24 024_尚硅谷react教程_类式组件中的构造器与pr...
P25 025-尚硅谷react教程_函数式组件使用props
function Item(props){
return (
<div>{props.content}</div>
)
}
Item.propTypes={
content:PropTypes.string.isRequired,
index:PropTypes.number,
deleteItem:PropTypes.func
}
Item.defaultProps={
avname:'koo'
}
P26 026_尚硅谷react教程_总结props
P27 027_尚硅谷react教程_字符串形式的ref
P28 028_尚硅谷react教程_回调形式的ref
P29 029_尚硅谷react教程_回调ref中调用次数的问题
1.ref="string"
2.<ul ref={ul=>this.ul=ul}> 这种多 但是更新state调用俩次
3.<button ref={this.saveClick}>onClick</button>
saveClick(e){
this.btn=e
}
P30 030-尚硅谷react教程-createRef的使用
4.btnRef=React.createRef() //只能一个
<button ref={this.btnRef}>onClick</button>
P31 031_尚硅谷react教程_总结ref
P32 032-尚硅谷react教程_react中的事件处理
P33 033-尚硅谷react教程-非受控组件
P34 034_尚硅谷react教程_受控组件
P35 035_尚硅谷react教程_高阶函数_函数柯里化
P36 036_尚硅谷react教程_不用柯里化的写法
P37 037_尚硅谷react教程_引出生命周期
ReactDOM.unmountComponentAtNode(document.getElementById('test')) 卸组件

P38 038_尚硅谷react教程_生命周期(旧)_组件挂载...1
P39 039_尚硅谷react教程_生命周期(旧)_setState流程1
P40 040_尚硅谷react教程_生命周期(旧)_forceUpda...0
P41 041_尚硅谷react教程_生命周期(旧)_父组件ren...1
P42 042_尚硅谷react教程_总结生命周期(旧)
P43 043-尚硅谷react教程-对比新旧生命周期
react17.0.1


除了componentWillUNmount 其他带will的钩子都要UNSFAE_
16.x还可以用 17.x不可用+
废弃三个 新增俩个 俩个少用
P44 044-尚硅谷react教程_getDerivedStateFromPro...1
static getDerivedStateFromProps(props,state){
return null //state object
}
P45 045-尚硅谷react教程-getSnapshotBeforeUpdate 1
getSnapshotBeforeUpdate 在更新前 获取快照
getSnapshotBeforeUpdate(prevProps,prevState){
return null
}
conponentDidUpdate(prevProps,prevState,snapshotValue){
}
P46 046-尚硅谷react教程-getSnapshotBeforeUpda 1
P47 047_尚硅谷react教程_总结生命周期(新)
P48 048-尚硅谷react教程-DOM的diffing算法
P49 049_尚硅谷react教程_初始化react脚手架
P50 050-尚硅谷react教程_脚手架文件介绍_public
create-react-app@4.0.0 视频的版本
P51 051_尚硅谷react教程_脚手架文件介绍_src
reportWebVitals.js 记录页面性能的
setupTest.js 单元测试的 组件测试
P52 052_尚硅谷react教程_一个简单的Hello组件
P53 053_尚硅谷react教程_样式的模块化
Koo.module.css 文件改名
import KooCss from './Koo.module.css'
<div className={KooCss.title}>调用css</div>
.title{
color: red;
}
P54 054_尚硅谷react教程-vscode中react插件的安装
vscode ES7 React/Redux/GraphQL/React-Native snippets 插件
rcc打入 快捷键
src
components
Home
Home.js
Home.css
P55 055_尚硅谷_react教程_组件化编码流程
P56 056_尚硅谷_react教程_TodoList案例_静态组件
P57 057_尚硅谷_react教程_TodoList案例_动态初始.
P59 059_尚硅谷_react教程_TodoList案例_鼠标移入.
P60 060_尚硅谷_react教程_TodoList案例_添加一个.
P58 058_尚硅谷_react教程_TodoList案例_添加todo
<input defaultChecked={true}/>
一上来就勾选 以后可以改
checked 写死了 不能改 要写onClick才可以改
<div onMouseEnter={this.hanle(true)}></div>
hanle(flag){
return ()=>{}
}
uuid npm i -S nanoid
P61 061_尚硅谷_react教程_TodoList案例_对props...(
yarn add prop-types
P62 062_尚硅谷_react教程_TodoList案例_删除一个...1
P63 063-尚硅谷_react教程_TodoList案例_实现底部...2
P64 064_尚硅谷_react教程_TodoList案例_总结Todo...
P65 065_尚硅谷_react教程_脚手架配置代理_方法1 2
"proxy":"http://127.0.0.1:5000"
package.json 加入 代理
src
setupProxy.js
const proxy=require('http-proxy-middleware')
module.exports=function(app){
app.use(
proxy('/api',{
target:'http://127.0.0.1:5000',
changeOrigin:true,
pathRewrite:{'^/api1':''}
})
)
}
P66 066_尚硅谷_react教程_脚手架配置代理_方法2 2
P67 067_尚硅谷_react教程_github搜索案例_静态组件1
P68 068_尚硅谷_react教程_github搜索案例_axios...2
P69 069_尚硅谷_react教程_github搜索案例_展示数据1
P70 070_尚硅谷_react教程_github搜索案例_完成案例2
P71 071_尚硅谷_react教程_消息订阅与发布技_pub...
工具库:PubSubJS npm i -S pubsub-js 兄弟组件通讯
https://github.com/mroderick/PubSubJS
import React, { Component,Fragment } from 'react'
import Home from './components/Home/Home.js'
import Item from './components/Item/Item.js'
export default class App extends Component {
render() {
return (
<Fragment>
<Home></Home>
<Item></Item>
</Fragment>
)
}
}
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
export default class Home extends Component {
componentDidMount(){
this.token=PubSub.subscribe('go',(msg,data)=>{
console.log(data)
})
}
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
render() {
return (
<div>Home</div>
)
}
}
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
export default class Item extends Component {
componentDidMount(){
PubSub.publish('go','hello react')
}
render() {
return (
<div>Item</div>
)
}
}
P72 072_尚硅谷_react教程_fetch发送请求
fetch fa起
_P73 073_尚硅谷_react教程_总结github搜索案例
P74 074_尚硅谷_react教程_对SPA应用的理解
.SPA的理解
单页Web应用(single page web application,SPA).
整个应用只有一个完整的页面。
点击页面中的链接不会刷新页面,只会做页面的局部更新。数据都需要通过 ajax 请求获取,并在前端异步展现。
P75 075_尚硅谷_react教程_对路由的理解
P76 076_尚硅谷_react教程_前端路由原理
P77 077_尚硅谷_react教程_路由的基本使用
docschina.org
react-router.docschina.org/web/guides/philosophy
http://react-router.docschina.org/web/guides/philosophy
yarn add react-router-dom@5
俩种路由
import React, { Component,Fragment } from 'react'
import Home from './components/Home/Home.js'
import Item from './components/Item/Item.js'
import { Link,BrowserRouter,Route } from 'react-router-dom'
export default class App extends Component {
render() {
return (
<Fragment>
<Link to="/about">About</Link>
<Link to="/home">Home</Link>
<Route path="/about" component={Item}></Route>
<Route path="/home" component={Home}></Route>
</Fragment>
)
}
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
P78 078_尚硅谷_react教程_路由组件与一般组件
P79 079_尚硅谷_react教程_NavLink的使用
import { Link,NavLink,BrowserRouter,Route } from 'react-router-dom'
<NavLink to="/about">About</NavLink>
NavLink 点谁加active类 默认
<NavLink activeClassName="active" to="/home">Home</NavLink> diy
index.jsx 文件
P80 080_尚硅谷_react教程_封装NavLink组件
82
import React, { Component,Fragment } from 'react'
import Home from './components/Home/Home.js'
import Item from './components/Item/Item.js'
import { Link,NavLink,BrowserRouter,Route } from 'react-router-dom'
import MyLink from './components/MyLink/index.jsx'
export default class App extends Component {
render() {
return (
<Fragment>
{/* <NavLink activeClassName="active" to="/about">About</NavLink>
<NavLink activeClassName="active" to="/home">Home</NavLink> */}
<MyLink to="/about">About</MyLink>
<MyLink to="/home">Home</MyLink>
<Route path="/about" component={Item}></Route>
<Route path="/home" component={Home}></Route>
</Fragment>
)
}
}
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom/cjs/react-router-dom.min'
export default class MyLink extends Component {
render() {
return (
//children 标签中间文字 属性在 this.props navlink有children属性
<NavLink activeClassName="active" {...this.props}/>
)
}
}
P81 081_尚硅谷_react教程_Switch的使用
import React, { Component,Fragment } from 'react'
import Home from './components/Home/Home.js'
import Item from './components/Item/Item.js'
import { Link,NavLink,BrowserRouter,Route,Switch } from 'react-router-dom'
import MyLink from './components/MyLink/index.jsx'
import Test from './components/Test/index.jsx'
export default class App extends Component {
render() {
return (
<Fragment>
{/* <NavLink activeClassName="active" to="/about">About</NavLink>
<NavLink activeClassName="active" to="/home">Home</NavLink> */}
<MyLink to="/about">About</MyLink>
<MyLink to="/home">Home</MyLink>
<Switch>
<Route path="/about" component={Item}></Route>
<Route path="/home" component={Home}></Route>
{/* 加switch组件一匹配了就不在继续 匹配相同 */}
<Route path="/home" component={Test}></Route>
</Switch>
</Fragment>
)
}
}
Switch的使用
1.通常情况下,path和component是一一对应的关系。
2.Switch可以提高路由匹配效率(单一匹配)。
P82 082_尚硅谷_react教程_解决样式丢失问题
_P83 083_尚硅谷_react教程_路由的模糊匹配与严格...1
{/* exact={true}精确匹配 不随便开 东西不对才开 默认模糊匹配 */}
<Route exact={true} path="/home" component={Home}></Route>
P84 084_尚硅谷_react教程_Redirect的使用
import { Link,NavLink,BrowserRouter,Route,Switch,Redirect } from 'react-router-dom'
<Redirect to="/home"/>
.一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
P85 085_尚硅谷_react教程_嵌套路由
import React, { Component,Fragment } from 'react'
import PubSub from 'pubsub-js'
import MyLink from '../MyLink'
import { Route,Switch,Redirect } from 'react-router-dom/cjs/react-router-dom.min'
import New from './New'
import Blog from './Blog'
export default class Home extends Component {
componentDidMount(){
// console.log(this.props)//路由传递一些东西
this.token=PubSub.subscribe('go',(msg,data)=>{
console.log(data)
})
}
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
render() {
return (
<Fragment>
<div>Home</div>
<ul>
<li><MyLink to="/home/new">new</MyLink></li>
<li><MyLink to="/home/blog">blog</MyLink></li>
</ul>
<Switch>
<Route path="/home/new" component={New}></Route>
<Route path="/home/blog" component={Blog}></Route>
<Redirect to="/home/new"/>
</Switch>
</Fragment>
)
}
}
P86 086_尚硅谷_react教程_向路由组件传递params...2
params
ajax query params body-urlencode-json
import React, { Component } from 'react'
import { Route,Switch,Redirect } from 'react-router-dom/cjs/react-router-dom.min'
import MyLink from '../../MyLink'
import Detail from './Detail'
export default class Blog extends Component {
state={
msg:[
{id:1,title:'vue'},
{id:2,title:'react'},
{id:3,title:'angular'}
]
}
render() {
return (
<div>
{
this.state.msg.map(item=>{
return (
<div key={item.id}>
<MyLink to={`/home/blog/detail/${item.id}/${item.title}`}>{item.title}</MyLink>
</div>
)
})
}
<Switch>
<Route path="/home/blog/detail/:id/:title" component={Detail}></Route>
</Switch>
</div>
)
}
}
import React, { Component } from 'react'
export default class Detail extends Component {
render() {
let {id,title} = this.props.match.params
return (
<div>id:{id}-title:{title}</div>
)
}
}
P87 087_尚硅谷_react教程_向路由组件传递search...1
import qs from 'querystring'
urldecedo编码 和对象互转
import React, { Component } from 'react'
import qs from 'querystring'
export default class Detail extends Component {
render() {
// let {id,title} = this.props.match.params
let search=this.props.location.search
let {id,title}=qs.parse(search.slice(1))
return (
<div>id:{id}-title:{title}</div>
)
}
}
import React, { Component } from 'react'
import { Route,Switch,Redirect } from 'react-router-dom/cjs/react-router-dom.min'
import MyLink from '../../MyLink'
import Detail from './Detail'
export default class Blog extends Component {
state={
msg:[
{id:1,title:'vue'},
{id:2,title:'react'},
{id:3,title:'angular'}
]
}
render() {
return (
<div>
{
this.state.msg.map(item=>{
return (
<div key={item.id}>
{/* params参数 */}
{/* <MyLink to={`/home/blog/detail/${item.id}/${item.title}`}>{item.title}</MyLink> */}
{/* search参数 */}
<MyLink to={`/home/blog/detail?id=${item.id}&title=${item.title}`}>{item.title}</MyLink>
</div>
)
})
}
<Switch>
{/* params参数 */}
{/* <Route path="/home/blog/detail/:id/:title" component={Detail}></Route> */}
{/* search参数 */}
<Route path="/home/blog/detail" component={Detail}></Route>
</Switch>
</div>
)
}
}
P88 088_尚硅谷_react教程_向路由组件传递state参数1
import React, { Component } from 'react'
import { Route,Switch,Redirect } from 'react-router-dom/cjs/react-router-dom.min'
import MyLink from '../../MyLink'
import Detail from './Detail'
export default class Blog extends Component {
state={
msg:[
{id:1,title:'vue'},
{id:2,title:'react'},
{id:3,title:'angular'}
]
}
render() {
return (
<div>
{
this.state.msg.map(item=>{
return (
<div key={item.id}>
{/* params参数 */}
{/* <MyLink to={`/home/blog/detail/${item.id}/${item.title}`}>{item.title}</MyLink> */}
{/* search参数 */}
{/* <MyLink to={`/home/blog/detail?id=${item.id}&title=${item.title}`}>{item.title}</MyLink> */}
{/* state参数 刷新还在 history记录*/}
<MyLink to={{pathname:'/home/blog/detail',state:{id:item.id,title:item.title}}}>{item.title}</MyLink>
</div>
)
})
}
<Switch>
{/* params参数 */}
{/* <Route path="/home/blog/detail/:id/:title" component={Detail}></Route> */}
{/* search参数 or state 不用带其他*/}
<Route path="/home/blog/detail" component={Detail}></Route>
</Switch>
</div>
)
}
}
import React, { Component } from 'react'
// import qs from 'querystring'
export default class Detail extends Component {
render() {
// params参数
// let {id,title} = this.props.match.params
// search参数
// let search=this.props.location.search
// let {id,title}=qs.parse(search.slice(1))
//state参数 刷新还在 history记录 清除缓存 加{}处理
let {id,title}=this.props.location.state||{}
return (
<div>id:{id}-title:{title}</div>
)
}
}
P89 089_尚硅谷_react教程_总结路由参数
1.params 2.search 3.state 顺序用 多用
_P90 090_尚硅谷_react教程_push与repalce
87
{/* replace={true} 默认push跳转 */}
<MyLink replace={true} to={{pathname:'/home/blog/detail',state:{id:item.id,title:item.title}}}>{item.title}</MyLink>
</div>
P91 091_尚硅谷_react教程_编程式路由导航
import React, { Component } from 'react'
import { Route,Switch,Redirect } from 'react-router-dom/cjs/react-router-dom.min'
import MyLink from '../../MyLink'
import Detail from './Detail'
export default class Blog extends Component {
state={
msg:[
{id:1,title:'vue'},
{id:2,title:'react'},
{id:3,title:'angular'}
]
}
pushShow=(id,title)=>{
console.log(this.props)
// this.props.history.push(`/home/blog/detail/${id}/${title}`) //params
// this.props.history.push(`/home/blog/detail?id=${id}&title=${title}`) //search
this.props.history.push(`/home/blog/detail`,{id,title}) //state
}
replaceShow=(id,title)=>{
return ()=>{
this.props.history.replace(`/home/blog/detail`,{id,title})
}
}
handle=()=>{
// this.props.history.go(-2) //go -1 2
// this.props.history.goBack()
this.props.history.goForward()
}
render() {
return (
<div>
{
this.state.msg.map(item=>{
return (
<div key={item.id}>
{/* params参数 */}
{/* <MyLink to={`/home/blog/detail/${item.id}/${item.title}`}>{item.title}</MyLink> */}
{/* search参数 */}
{/* <MyLink to={`/home/blog/detail?id=${item.id}&title=${item.title}`}>{item.title}</MyLink> */}
{/* state参数 刷新还在 history记录*/}
{/* replace={true} 默认push跳转 */}
<MyLink to={{pathname:'/home/blog/detail',state:{id:item.id,title:item.title}}}>{item.title}</MyLink>
<button onClick={()=>this.pushShow(item.id,item.title)}>push</button>
<button onClick={this.replaceShow(item.id,item.title)}>replace</button>
</div>
)
})
}
<Switch>
{/* params参数 */}
{/* <Route path="/home/blog/detail/:id/:title" component={Detail}></Route> */}
{/* search参数 or state 不用带其他*/}
<Route path="/home/blog/detail" component={Detail}></Route>
</Switch>
<button onClick={this.handle}>操作</button>
</div>
)
}
}
P92 092-尚硅谷_react教程_withRouter的使用
withRouter可以加工一般组件,让:一般组件具备路由组件所特有的API
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
class Header extends Component {
handle = () => {
// this.props.history.go(-2) //go -1 2
this.props.history.goBack()
// this.props.history.goForward()
}
render() {
return (
<div>
Header
<button onClick={this.handle}>操作</button>
</div>
)
}
}
export default withRouter(Header)
P93 093-尚硅谷_react教程_BrowserRouter与Hash...
:十三、BrowserRouter 与HashRouter的区别
1.底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2.url表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3,刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中.
(2).HashRouter刷新后会导致路由state参数的丢失。
4,备注:HashRouter可以用于解决一些路径错误相关的问题。
P94 094_尚硅谷_react教程_antd的基本使用
material-ui 国外
ant-design 国内蚂蚁金服 : https://ant.design/index-cn
视频ant-design4.0
管理系统多用
npm install antd --save
新版不用引入css
P95 095_尚硅谷_react教程_antd样式的按需引入
3.x版本按需引入
5.x tree shake
yarn eject 暴露webpack配置文件
https://ant-design.antgroup.com/docs/react/use-with-create-react-app-cn
P96 096_尚硅谷_react教程_antd自定义主题
P97 097_尚硅谷_react教程_redux简介
pubsub怕沙 redux绿大x
.redux 是什么
1.redux 是一个专门用于做状态管理的 JS 库(不是 react 插件库)。
2.它可以用在react,angular,vue等项目中,但基本与react配合使用。+
3.作用:集中式管理 react 应用中多个组件共享的状态。
同vuex 能不用就不用 吃力时用
P98 098_尚硅谷_react教程_redux工作流程


action reducer store components
_P99 099_尚硅谷_react教程_求和案例_纯react版
P100 100_尚硅谷_react教程_求和案例_redux精简版
传参数 事件用箭头函数内联 方法用高阶函数
yarn install redux
带s的可以有多个actions reduces
1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
reducer 纯函数
store.subscribe redux状态改变都调用这个回调函数
this.setState({}) 空对象也更新 shouldComponentUpdate阀门控制下性能
Count component
import React, { Component } from 'react'
import store from '../../redux/store'
export default class Count extends Component {
// componentDidMount(){
// store.subscribe(()=>{
// this.setState({})
// })
// }
inc=()=>{
let value= this.select.value
store.dispatch({type:'inc',data:value*1})
}
deinc=()=>{
let value= this.select.value
store.dispatch({type:'deinc',data:value*1})
}
incifodd=()=>{
let value= this.select.value
let count=store.getState()
if(count%2!==0){
store.dispatch({type:'inc',data:value*1})
}
}
asyncinc=()=>{
let value= this.select.value
setTimeout(() => {
store.dispatch({type:'inc',data:value*1})
}, 500);
}
render() {
return (
<div>
<h1>current num:{store.getState()}</h1>
<div>
<select ref={select=>this.select=select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={this.inc}>inc</button>
<button onClick={this.deinc}>deinc</button>
<button onClick={this.incifodd}>inc if odd</button>
<button onClick={this.asyncinc}>async inc</button>
</div>
</div>
)
}
}
跟index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
//不会全部渲染 dom diff 差别的出现
store.subscribe(()=>{
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
})
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
redux/store.js
import { createStore } from "redux";
import count_reducer from "./count_reducer";
export default createStore(count_reducer)
redux/count_reducer.js
let initState=0 //init is undefined
export default function(preState=initState,action){
let {type,data}=action
switch (type) {
case 'inc':
return preState+data
case 'deinc':
return preState-data
default:
return preState
}
}
P101 101_尚硅谷_react教程_求和案例_redux完整版
Count Component
import React, { Component } from 'react'
import store from '../../redux/store'
import { createIncAction,createDeincAction } from '../../redux/count_action'
export default class Count extends Component {
// componentDidMount(){
// store.subscribe(()=>{
// this.setState({})
// })
// }
inc=()=>{
let value= this.select.value*1
store.dispatch(createIncAction(value))
}
deinc=()=>{
let value= this.select.value*1
store.dispatch(createDeincAction(value))
}
incifodd=()=>{
let value= this.select.value*1
let count=store.getState()
if(count%2!==0){
store.dispatch(createIncAction(value))
}
}
asyncinc=()=>{
let value= this.select.value*1
setTimeout(() => {
store.dispatch(createIncAction(value))
}, 500);
}
render() {
return (
<div>
<h1>current num:{store.getState()}</h1>
<div>
<select ref={select=>this.select=select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={this.inc}>inc</button>
<button onClick={this.deinc}>deinc</button>
<button onClick={this.incifodd}>inc if odd</button>
<button onClick={this.asyncinc}>async inc</button>
</div>
</div>
)
}
}
redux/count_action.js
import {INC,DEINC} from './constant'
export const createIncAction=data=>({type:INC,data})
export const createDeincAction=data=>({type:DEINC,data})
redux/count_reducer.js
import {INC,DEINC} from './constant'
let initState=0 //init is undefined
export default function(preState=initState,action){
let {type,data}=action
switch (type) {
case INC:
return preState+data
case DEINC:
return preState-data
default:
return preState
}
}
redux/constant.js
export const INC='inc'
export const DEINC='deinc'
P102 102_尚硅谷_react教程_求和案例_异步action版
yarn add redux-thunk 开启异步action
Count Component
import React, { Component } from 'react'
import store from '../../redux/store'
import { createIncAction,createDeincAction,createIncAsyncAction } from '../../redux/count_action'
export default class Count extends Component {
// componentDidMount(){
// store.subscribe(()=>{
// this.setState({})
// })
// }
inc=()=>{
let value= this.select.value*1
store.dispatch(createIncAction(value))
}
deinc=()=>{
let value= this.select.value*1
store.dispatch(createDeincAction(value))
}
incifodd=()=>{
let value= this.select.value*1
let count=store.getState()
if(count%2!==0){
store.dispatch(createIncAction(value))
}
}
asyncinc=()=>{
let value= this.select.value*1
// setTimeout(() => {
// store.dispatch(createIncAction(value))
// }, 500);
store.dispatch(createIncAsyncAction(value,500))
}
render() {
return (
<div>
<h1>current num:{store.getState()}</h1>
<div>
<select ref={select=>this.select=select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={this.inc}>inc</button>
<button onClick={this.deinc}>deinc</button>
<button onClick={this.incifodd}>inc if odd</button>
<button onClick={this.asyncinc}>async inc</button>
</div>
</div>
)
}
}
redux/store.js
import { createStore,applyMiddleware } from "redux";
import count_reducer from "./count_reducer";
import { thunk } from "redux-thunk";
export default createStore(count_reducer,applyMiddleware(thunk))
redux/count_action.js
import {INC,DEINC} from './constant'
//同步action,就是指action的值为Object类型的一般对象
export const createIncAction=data=>({type:INC,data})
export const createDeincAction=data=>({type:DEINC,data})
//异步action,就是指action的值为函数
export const createIncAsyncAction=(data,time)=>{
return (dispatch)=>{
setTimeout(()=>{
dispatch(createIncAction(data))
},time)
}
}
P103 103_尚硅谷_react教程_对react-redux的理解

P104 104_尚硅谷_react教程_连接容器组件与UI组件
yarn add react-redux
P105 105-尚硅谷_react教程_react-redux基本使用
App.js
import React, { Component,Fragment } from 'react'
import Count from './containers/Count'
import store from './redux/store'
export default class App extends Component {
render() {
return (
<Fragment>
<Count store={store}></Count>
</Fragment>
)
}
}
src/containers/Count/index.jsx
import CountUI from '../../components/Count'
import { connect } from 'react-redux'
import {createIncAction,createDeincAction,createIncAsyncAction} from '../../redux/count_action'
function mapStateToProps(state){
return {
count:state
}
}
function mapDispatchToProps(dispatch){
return {
jia:num=>dispatch(createIncAction(num)),
jian:num=>dispatch(createDeincAction(num)),
jiaAsync:(num,time)=>dispatch(createIncAsyncAction(num,time)),
}
}
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
src/components/Count/index.jsx
import React, { Component } from 'react'
export default class Count extends Component {
inc=()=>{
let value= this.select.value*1
this.props.jia(value)
}
deinc=()=>{
let value= this.select.value*1
this.props.jian(value)
}
incifodd=()=>{
let value= this.select.value*1
if(this.props.count&2!==0){
this.props.jia(value)
}
}
asyncinc=()=>{
let value= this.select.value*1
this.props.jiaAsync(value,500)
}
render() {
return (
<div>
<h1>current num:{this.props.count}</h1>
<div>
<select ref={select=>this.select=select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={this.inc}>inc</button>
<button onClick={this.deinc}>deinc</button>
<button onClick={this.incifodd}>inc if odd</button>
<button onClick={this.asyncinc}>async inc</button>
</div>
</div>
)
}
}
P106 106_尚硅谷_react教程_优化1_简写mapDispatch
react-redux api优化简写 api调用
src/containers/Count/index.jsx
import CountUI from '../../components/Count'
import { connect } from 'react-redux'
import {createIncAction,createDeincAction,createIncAsyncAction} from '../../redux/count_action'
export default connect(
state=>({count:state}),
{
jia:createIncAction,
jian:createDeincAction,
jiaAsync:createIncAsyncAction,
}
)(CountUI)
P107 107_尚硅谷_react教程_优化2_Provider组件的..
继续优化
跟/index.js 入口
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './redux/store';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// react-redux connect已经检测了
//不会全部渲染 dom diff 差别的出现
// store.subscribe(()=>{
// root.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>
// );
// })
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App.js
import React, { Component,Fragment } from 'react'
import Count from './containers/Count'
export default class App extends Component {
render() {
return (
<Fragment>
<Count></Count>
</Fragment>
)
}
}
P108 108_尚硅谷_react教程_优化3_整合UI组件与….
叫Component containers 都可以
del src/components/Count/index.jsx
合并在一个文件
src/containers/Count/index.jsx
import { connect } from 'react-redux'
import {createIncAction,createDeincAction,createIncAsyncAction} from '../../redux/count_action'
import React, { Component } from 'react'
class Count extends Component {
inc=()=>{
let value= this.select.value*1
this.props.jia(value)
}
deinc=()=>{
let value= this.select.value*1
this.props.jian(value)
}
incifodd=()=>{
let value= this.select.value*1
if(this.props.count&2!==0){
this.props.jia(value)
}
}
asyncinc=()=>{
let value= this.select.value*1
this.props.jiaAsync(value,500)
}
render() {
return (
<div>
<h1>current num:{this.props.count}</h1>
<div>
<select ref={select=>this.select=select}>
<option value="1">1</option>
<option value="2">2</option>
</select>
<button onClick={this.inc}>inc</button>
<button onClick={this.deinc}>deinc</button>
<button onClick={this.incifodd}>inc if odd</button>
<button onClick={this.asyncinc}>async inc</button>
</div>
</div>
)
}
}
export default connect(
state=>({count:state}),
{
jia:createIncAction,
jian:createDeincAction,
jiaAsync:createIncAsyncAction,
}
)(Count)
P109 109_尚硅谷_react教程_数据共享-编写Person...
P110 110_尚硅谷_react教程_数据共享-编写Person...
P111 111_尚硅谷_react教程_数据共享_完成数据...
多个reducers
src/containers/Person/index.jsx
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import {createAddPersonAction} from '../../redux/actions/person'
class Person extends Component {
add=()=>{
let obj={id:nanoid(),name:this.input.value}
this.props.addPerson(obj)
}
render() {
return (
<div>
<label htmlFor="name">name:</label>
<input type="text" id='name' ref={input=>this.input=input} />
<button onClick={this.add}>add</button>
<p>上方组件和是:{this.props.he}</p>
<ul>
{
this.props.rens.map(item=>{
console.log(item,222222)
return (
<li key={item.id}>{item.name}</li>
)
})
}
</ul>
</div>
)
}
}
export default connect(
state=>({rens:state.rens,he:state.he}),
{
addPerson:createAddPersonAction
}
)(Person)
src/redux/store.js
import { createStore,applyMiddleware,combineReducers } from "redux";
import count_reducer from "./reducers/count";
import person_reducer from "./reducers/person";
import { thunk } from "redux-thunk";
let allReducer=combineReducers({
he:count_reducer,
rens:person_reducer
})
export default createStore(allReducer,applyMiddleware(thunk))
P112 112_尚硅谷_react教程_纯函数
7.8.纯函数和高阶函数
7.8.1.纯函数
1.一类特别的函数:只要是同样的输入(实参),必定得到同样的输出(返回)
2.必须遵守以下一些约束
1)不得改写参数数据
2)不会产生任何副作用,例如网络请求,输入和输出设备3)不能调用 Date.now)或者 Math.random(等不纯的方法
3.redux的reducer函数必须是一个纯函数
P113 113_尚硅谷_react教程_redux开发者工具
Redux DevTools
安装 yarn add redux-devtools-extension
src/redux/store.js
import { createStore,applyMiddleware,combineReducers } from "redux";
import count_reducer from "./reducers/count";
import person_reducer from "./reducers/person";
import { thunk } from "redux-thunk";
import {composeWithDevTools} from 'redux-devtools-extension'
let allReducer=combineReducers({
he:count_reducer,
rens:person_reducer
})
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))
P114 114_尚硅谷_react教程_最终版
P115 115_尚硅谷_react教程_项目打包运行
npm run build 打包
npm i serve -g
serve -s build
P116 116_尚硅谷_react教程_扩展1_setState
setState更新状态的2种写法
(1).setState(stateChange,[callback])------对象式的setState
1.stateChange为状态改变对象(该对象可以体现出状态的更改)
2.callback是可选的回调函数,它在状态更新完毕、界面也更新后(render调用后)才被调用
(2).setState(updater,[callback])------函数式的setState
1.updater为返回stateChange对象的函数。
2.updater可以接收到state和props.
4.callback是可选的回调的数,它在状态更新、界面也更新后(render调用后)才被调用。
总结:
1.对象式的setState是函数式的setState的简写方式(语法糖)
2.使用原则:
(1).如果新状态不依赖于原状态 => 使用对象方式
(2).如果新状态依赖于原状态=>使用函数方式
(3).如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中读取
import React, { Component } from 'react'
export default class Demo extends Component {
state = {
count: 0
}
add = () => {
// this.setState({
// count:this.state.count+1
// },()=>{
// console.log(this.state.count) //this.setState异步的 在回调才获取改后的值
// })
this.setState((state,props)=>{
return {
count:state.count+props.num
}
})
}
render() {
return (
<div>
<p>Count:{this.state.count}</p>
<button onClick={this.add}>add</button>
</div>
)
}
}
P117 117_尚硅谷_react教程_扩展2_lazyLoad
路由组件的lazyLoad
import React, { Component, Fragment, lazy, Suspense } from 'react'
// import Home from './Home'
// import Item from './Item'
import { Link, Route } from 'react-router-dom'
import Loading from './Loading'
const Home = lazy(() => import('./Home'))
const Item = lazy(() => import('./Item'))
export default class App extends Component {
render() {
return (
<Fragment>
<Link to="/about">About</Link>
<Link to="/home">Home</Link>
{/* <Suspense fallback={<del>Loading...</del>}></Suspense> 直接写也是虚拟dom 组件 */}
{/* 只能普通导入组件 请求中显示的 和骨架屏差不多 */}
<Suspense fallback={<Loading/>}>
<Route path="/about" component={Item}></Route>
<Route path="/home" component={Home}></Route>
</Suspense>
</Fragment>
)
}
}
P118 118_尚硅谷_react教程_扩展3_stateHook
1.React Hook/Hooks是什么?
(1).Hook是React 16.8.0版本增加的新特性/新语法(2).可以让你在函数组件中使用 state 以及其他的 React 特性
2.三个常用的Hook
(1).State Hook:React.useState()
(2).Effect Hook:React.useEffect()
(3).Ref Hook:React.useRef()
React.useState render 1+N 底层做了处理
import React from 'react'
export default function Deme(props) {
let [count,setCount]=React.useState(0)
let add=()=>{
// setCount(count+props.num)
setCount((preCount)=>count+props.num)
}
return (
<div>
<p>count:{count}</p>
<button onClick={add}>add</button>
</div>
)
}
P119 119_尚硅谷_react教程_扩展4_EffectHook
effecthook相当生命周期 副作用
Demo.js
import React from 'react'
// import ReactDOM from 'react-dom'
import root from '../../index'
export default function Deme(props) {
let [count,setCount]=React.useState(0)
// React.useEffect 相当生命周期
React.useEffect(()=>{
let timer=setInterval(()=>{
setCount((count)=>count+1)
},1000)
return ()=>{
//return 相当componentWillUnmount
clearInterval(timer)
}
},[])//不写第二参数 全部检测 [count]检测count相当componentDidUpdate 写[]相当componentDidMount
let add=()=>{
// setCount(count+props.num)
setCount((preCount)=>count+props.num)
}
let unmount=()=>{
// ReactDOM.unmountComponentAtNode(document.getElementById('root')) //旧版
root.unmount()
}
return (
<div>
<p>count:{count}</p>
<button onClick={add}>add</button>
<button onClick={unmount}>unmount</button>
</div>
)
}
index.js 入口
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
{/* <App root={root}/> */}
<App/>
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
export default root
可以把 useEffect Hook 看做如下三个函数的组合
component DidMount()
componentDidupdate()
componentwi 11Unmount()
P120 120尚硅谷react教程扩展5 RefHook
Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
语法:const refContainer = useRef()
作用:保存标签对象,功能与React.createRef()一样
专人专用
import React from 'react'
// import ReactDOM from 'react-dom'
import root from '../../index'
export default function Deme(props) {
let [count,setCount]=React.useState(0)
let myRef=React.useRef()
// React.useEffect 相当生命周期
React.useEffect(()=>{
let timer=setInterval(()=>{
setCount((count)=>count+1)
},1000)
return ()=>{
//return 相当componentWillUnmount
clearInterval(timer)
}
},[])//不写第二参数 全部检测 [count]检测count相当componentDidUpdate 写[]相当componentDidMount
let add=()=>{
// setCount(count+props.num)
setCount((preCount)=>count+props.num)
}
let unmount=()=>{
// ReactDOM.unmountComponentAtNode(document.getElementById('root')) //旧版
root.unmount()
}
let show=()=>{
alert(myRef.current.value)
}
return (
<div>
<div><input type="text" ref={myRef}/></div>
<p>count:{count}</p>
<button onClick={add}>add</button>
<button onClick={unmount}>unmount</button>
<button onClick={show}>showInput</button>
</div>
)
}
P121 121_尚硅谷_react教程_扩展6_Fragment
Fragment
import React,{Fragment} from 'react'
export default function Deme() {
return (
// fragment 只能写key不能其他props
<Fragment key={1}>
<div>hello</div>
{/* 标签同fragment效果 但是不能写key 任何 */}
<>
<span>react</span>
</>
</Fragment>
)
}
P122 122_尚硅谷_react教程_扩展7_Context
5.Context理解
一种组件间通信方式,常用于【祖组件】与【后代组件】间通信
注意
在应用开发中一般不用context一般都用它的封装react插件 react-redux
import React, { Component } from 'react'
import './index.css'
let MyContext = React.createContext()
let { Provider,Consumer } = MyContext
export default class A extends Component {
state = {
name: 'koo',
age: 28
}
render() {
let { name, age } = this.state
return (
<div className='parent'>
A组件
<Provider value={{ name, age }}>
<B></B>
</Provider>
</div>
)
}
}
class B extends Component {
render() {
return (
<div className='child'>
B组件
<C></C>
</div>
)
}
}
//只能类组件使用
// class C extends Component {
// static contextType=MyContext
// render() {
// let {name,age}=this.context
// return (
// <div className='grand'>
// C组件
// <del>{name}-{age}</del>
// </div>
// )
// }
// }
// 函数和类组件使用
function C() {
return (
<div className='grand'>
C组件
<Consumer>
{
value=><del>{value.name}-{value.age}</del>
}
</Consumer>
</div>
)
}
P123 123_尚硅谷_react教程_扩展8_PureComponent
Component的2个问题
1.只要执行setState(),即使不改变状态数据,组件也会重新render()2.只当前组件重新render(),就会自动重新render子组件 ==>效率低效率高的做法
只有当组件的state或props数据发生改变时才重新render()
原因
Component中的shouldComponentUpdate()总是返回true解决
PureComponent pu-componet 重写shouldComponentUpdate 智能控制true 性能优化
import React, { Component,PureComponent } from 'react'
export default class Parent extends PureComponent {
state={
name:'koo',
stus:['小李','小张']
}
// 用Component性能优化 用了PureComponent不用写 底层实现了
// shouldComponentUpdate(nextProps,nextState){
// return !this.state.name===nextState.name
// }
addStu=()=>{
// PureComponent 这样写不起作用 操作同一个堆地址 push unshift等方法
let stus=this.state.stus
let newStu='小刘'
// stus.unshift(newStu)
// this.setState({stus})
this.setState({stus:[newStu,...stus]})
}
changeName=()=>{
this.setState({name:'John'})
//PureComponent 这样写不起作用 操作同一个
// let obj=this.state
// obj.name='john'
// this.setState(obj)
}
render() {
console.log('parent-render')
let {name}=this.state
return (
<div>
Parent:{name}
<button onClick={this.changeName}>changeName</button>
<br />
{this.state.stus}
<button onClick={this.addStu}>addStu</button>
<Child name={name}></Child>
</div>
)
}
}
class Child extends PureComponent {
// shouldComponentUpdate(nextProps,nextState){
// return !this.props.name===nextProps.name
// }
render() {
console.log('child-render')
return (
<div>Child</div>
)
}
}
P124 124_尚硅谷_react教程_扩展9_renderProps
renderProps 相当vue 中的插槽
import React, { Component } from 'react'
import './index.css'
export default class A extends Component {
render() {
return (
<div className='parent'>
A组件
{/* <B>
<C></C>
</B> */}
<B render={(name)=><C name={name}/>}></B>
</div>
)
}
}
class B extends Component {
state = {
name: 'koo',
age: 28
}
render() {
let { name, age } = this.state
return (
<div className='child'>
B组件
{/* {this.props.children} */}
{this.props.render(name)}
</div>
)
}
}
//只能类组件使用
class C extends Component {
render() {
return (
<div className='grand'>
C组件
{this.props.name}
</div>
)
}
}
P125 125_尚硅谷_react教程_扩展10_ErrorBoundary
错误边界
理解:
错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面特点:
只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
子组件出错 不向外扩 影响到组件 父组件做错误判断 用在生产环境的 开发环境用一会就继续error
当Parent的子组件出现报错时候,会触发getDerivedStateFromError调用,并携带错误信息
componentDidCatch'统计错误此处,发送给后台');
import React, { Component } from 'react'
import Child from './Child'
export default class Parent extends Component {
state={
hasError:''
}
//用在生产环境的 开发环境用一会就继续error
static getDerivedStateFromError(error){
return {
hasError:error
}
}
componentDidCatch(){
console.log('统计错误此处,发送给后台')
}
render() {
return (
<div>
Parent
{this.state.hasError?<h1>网络不稳定</h1>:<Child/>}
</div>
)
}
}
import React, { Component } from 'react'
export default class Child extends Component {
state ={
// list:[
// {id:1,name:'koo'}
// ]
list:''
}
render() {
return (
<div>
{
this.state.list.map(item=>{
return <p key={item.id}>{item.name}</p>
})
}
</div>
)
}
}
P126 126_尚硅谷_react教程_组件间通信方式总结
9.组件通信方式总结
组件间的关系:
父子组件
兄弟组件(非嵌套组件)祖孙组件(跨级组件)几种通信方式:
1.props:
(1).children props
(2).render props
2.消息订阅-发布:
pubs-sub,event等等
3.集中式管理:
redux、dva等等
4.conText:生产者-消费者模式比较好的搭配方式:
父子组件:props兄弟组件:消息订阅-发布、集中式管理
祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(开发用的少,封装插件用的多)
P127 127_尚硅谷_ReactRouter6教程_课程说明
2021
1.React Router以三个不同的包发布到npm上,它们分别为:
1.react-router:路由的核心库,提供了很多的:组件、钩子。
2.react-router-dom:包含react-router所有内容,并添加一些专门用于 DoM 的组件,例如
3.react-router-native:包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:
2.与React Router 5.x 版本相比,改变了什么?
1.内置组件的变化:移除
2.语法的变化:component={About}变为 element={
3.新增多个hook:useParams、useNavigate、useMatch等。
4.官方明确推荐函数式组件了!!!
P128 128_尚硅谷_ReactRouter6教程_一级路由
npm i -S react-router-dom
import Home from './components/Home'
import Item from './components/Item'
import Loading from './components/Loading'
import { NavLink,Routes,Route } from 'react-router-dom';
function App() {
return (
<div>
<NavLink to={'/home'}>home</NavLink>
<NavLink to={'/item'}>item</NavLink>
<Routes>
<Route path='/home' element={<Home/>}></Route>
<Route path='/item' element={<Item/>}></Route>
</Routes>
</div>
);
}
export default App;
_P129 129_尚硅谷_ReactRouter6教程_重定向
navigate 只要挂载就切换
.
import Home from './components/Home'
import Item from './components/Item'
import Loading from './components/Loading'
import { NavLink,Routes,Route,Navigate } from 'react-router-dom';
function App() {
return (
<div>
<NavLink to={'/home'}>home</NavLink>
<NavLink to={'/item'}>item</NavLink>
<Routes>
<Route path='/home' element={<Home/>}></Route>
<Route path='/item' element={<Item/>}></Route>
<Route path='/' element={<Navigate to={'/home'}/>}></Route>
</Routes>
</div>
);
}
export default App;
import React,{useState} from 'react'
import { Navigate } from 'react-router-dom'
export default function Home() {
let [num,setNum]=useState(0)
let addNum=()=>{
setNum(num=>num+1)
}
return (
<div>
<p>Home</p>
{num===2?<Navigate to={'/item'} replace></Navigate>:<h1>{num}</h1>}
<button onClick={addNum}>add</button>
</div>
)
}
P130 130-尚硅谷_ReactRouter6教程-NavLink高亮
import Home from './components/Home'
import Item from './components/Item'
import Loading from './components/Loading'
import { NavLink, Routes, Route, Navigate } from 'react-router-dom';
function App() {
// 实现自定义高亮 active
function computedClassName({ isActive }) {
return isActive ? 'class1 class2' : ''
}
return (
<div>
<NavLink className={computedClassName} to={'/home'}>home</NavLink>
<NavLink to={'/item'}>item</NavLink>
<Routes>
<Route path='/home' element={<Home />}></Route>
<Route path='/item' element={<Item />}></Route>
<Route path='/' element={<Navigate to={'/home'} />}></Route>
</Routes>
</div>
);
}
export default App;
P131 131_尚硅谷_ReactRouter6教程_useRoutes路...
根据路由表生成对应的路由规则
src/routes/index.js
import Home from '../components/Home'
import Item from '../components/Item'
import { Navigate } from 'react-router-dom'
export default [
{
path:'/home',
element:<Home/>
},
{
path:'/item',
element:<Item/>
},
{
path:'/',
element:<Navigate to={'/home'}/>
}
]
import { NavLink,useRoutes } from 'react-router-dom';
import routes from './routes';
function App() {
let element=useRoutes(routes)
return (
<div>
<NavLink to={'/home'}>home</NavLink>
<NavLink to={'/item'}>item</NavLink>
{element}
</div>
);
}
export default App;
P132 132_尚硅谷_ReactRouter6教程_嵌套路由
. ./ / navlink to写法
src/routes/index.jsx
import Home from '../components/Home'
import Item from '../components/Item'
import New from '../components/Item/New'
import Blog from '../components/Item/Blog'
import { Navigate } from 'react-router-dom'
export default [
{
path:'/home',
element:<Home/>
},
{
path:'/item',
element:<Item/>,
children:[
{
path:'new',
element:<New/>
},
{
path:'blog',
element:<Blog/>
},
{
path:'',
element:<Navigate to={'blog'}/>
}
]
},
{
path:'/',
element:<Navigate to={'/home'}/>
}
]
App.js
import { NavLink,useRoutes } from 'react-router-dom';
import routes from './routes';
function App() {
let element=useRoutes(routes)
return (
<div>
<NavLink to={'/home'}>home</NavLink>
<NavLink end to={'/item'}>item</NavLink>
{/* end父级失去高亮 */}
{element}
</div>
);
}
export default App;
Item component
import React, { Component } from 'react'
import { NavLink,Outlet } from 'react-router-dom'
export default class Item extends Component {
render() {
return (
<div>
<ul>
<li><NavLink to={'new'}>new</NavLink></li>
<li><NavLink to={'blog'}>blog</NavLink></li>
</ul>
{/* 相当vue的router-view */}
<Outlet></Outlet>
</div>
)
}
}
P133 133_尚硅谷_ReactRouter6教程_路由的param.
routes
import Home from '../components/Home'
import Item from '../components/Item'
import New from '../components/Item/New'
import Blog from '../components/Item/Blog'
import Detail from '../components/Item/Blog/Detail'
import { Navigate } from 'react-router-dom'
export default [
{
path:'/home',
element:<Home/>
},
{
path:'/item',
element:<Item/>,
children:[
{
path:'new',
element:<New/>
},
{
path:'blog',
element:<Blog/>,
children:[
{
path:'detail/:id/:name',
element:<Detail/>
},
]
},
{
path:'',
element:<Navigate to={'blog'}/>
}
]
},
{
path:'/',
element:<Navigate to={'/home'}/>
}
]
import React, { useState } from 'react'
import { Link,Outlet } from 'react-router-dom'
export default function Blog() {
let [msg, setMsg] = useState([
{ id: 1, name: 'koo' },
{ id: 2, name: 'john' }
])
return (
<div>
{
msg.map(item=>{
return (
<div>
<Link to={`detail/${item.id}/${item.name}`}>{item.name}</Link>
</div>
)
})
}
<Outlet></Outlet>
</div>
)
}
import React from 'react'
import { useParams,useMatch } from 'react-router-dom'
export default function () {
// 1.params
let params=useParams()
//useMatch少用
// let match=useMatch('/item/blog/detail/:id/:name')
// console.log(match).
return (
<div><del>{params.id}-{params.name}</del></div>
)
}
P134 134_尚硅谷_ReactRouter6教程_路由的search..
{
path:'blog',
element:<Blog/>,
children:[
{
path:'detail',
element:<Detail/>
},
]
},
import React, { useState } from 'react'
import { Link,Outlet } from 'react-router-dom'
export default function Blog() {
let [msg, setMsg] = useState([
{ id: 1, name: 'koo' },
{ id: 2, name: 'john' }
])
return (
<div>
{
msg.map(item=>{
return (
<div>
<Link to={`detail?id=${item.id}&name=${item.name}`}>{item.name}</Link>
</div>
)
})
}
<Outlet></Outlet>
</div>
)
}
import React from 'react'
import { useSearchParams,useLocation } from 'react-router-dom'
export default function () {
// search
let [search,setSearch]=useSearchParams()
let id=search.get('id')
let name=search.get('name')
console.log(useLocation())
let change=()=>{
setSearch('id=8&name=hello')
}
return (
<div>
<del>{id}-{name}</del>
<button onClick={change}>change</button>
</div>
)
}
P135 135_尚硅谷_ReactRouter6教程_路由的state.
import React, { useState } from 'react'
import { Link,Outlet } from 'react-router-dom'
export default function Blog() {
let [msg, setMsg] = useState([
{ id: 1, name: 'koo' },
{ id: 2, name: 'john' }
])
return (
<div>
{
msg.map(item=>{
return (
<div>
<Link to={`detail`} state={{id:item.id,name:item.name}}>{item.name}</Link>
</div>
)
})
}
<Outlet></Outlet>
</div>
)
}
import React from 'react'
import { useLocation } from 'react-router-dom'
export default function () {
// state
let {state:{id,name}}=useLocation()
return (
<div>
<del>{id}-{name}</del>
</div>
)
}
P136 136_尚硅谷_ReactRouter6教程-编程式路由导航
import React, { useState } from 'react'
import { Link,Outlet,useNavigate } from 'react-router-dom'
export default function Blog() {
let navigate=useNavigate()
let [msg, setMsg] = useState([
{ id: 1, name: 'koo' },
{ id: 2, name: 'john' }
])
let go=()=>{
// navigate(-1) //前进1 -1 后退1
// navigate('detail?id=1&name=kk')
// navigate('detail/1/kk')
navigate('detail',{
replace:false,
state:{
id:8,
name:'hello react'
}
})
}
return (
<div>
{
msg.map(item=>{
return (
<div key={item.id}>
<Link to={`detail`} state={{id:item.id,name:item.name}}>{item.name}</Link>
<button onClick={go}>go</button>
</div>
)
})
}
<Outlet></Outlet>
</div>
)
}
P137 137-尚硅谷_ReactRouter6教程_uselnRouter...
import { NavLink,useRoutes,useInRouterContext } from 'react-router-dom';
import routes from './routes';
function App() {
let element=useRoutes(routes)
console.log(useInRouterContext()) //<BrowserRouter>路由器包裹的都为true
return (
<div>
<NavLink to={'/home'}>home</NavLink>
<NavLink end to={'/item'}>item</NavLink>
{/* end父级失去高亮 */}
{element}
</div>
);
}
export default App;
P138 138_尚硅谷_ReactRouter6教程_useNavigatio...
8.useNavigationType()
1.作用:返回当前的导航类型(用户是如何来到当前页面的)。
2.返回值:POP、PUSH、REPLACE。
3.备注:POP 是指在浏览器中直接打开了这个路由组件(刷新页面)。
import React from 'react'
import { useNavigationType } from 'react-router-dom'
export default function New() {
console.log(useNavigationType()) //默认push跳转 pop刷新 replace替换
return (
<div>New</div>
)
}
P139 139_尚硅谷_ReactRouter6教程_useOutlet
9.useOutlet()
1.作用:用来呈现当前组件中渲染的嵌套路由。
如果嵌套路由没有挂载,则result为null
,如果嵌套路由已经挂载,则展示嵌套的路由对象
import { NavLink,Outlet,useOutlet} from 'react-router-dom'
import React from 'react'
export default function Item() {
console.log(useOutlet(),'outlet') //挂载 输出组件路由对象 在outlet组件用
return (
<div>
<ul>
<li><NavLink to={'new'}>new</NavLink></li>
<li><NavLink to={'blog'}>blog</NavLink></li>
</ul>
{/* 相当vue的router-view */}
<Outlet></Outlet>
</div>
)
}
P140 140-尚硅谷_ReactRouter6教程_useOutletuse..
import React from 'react'
import { useNavigationType,useResolvedPath } from 'react-router-dom'
export default function New() {
console.log(useNavigationType()) //默认push跳转 pop刷新 replace替换
console.log(useResolvedPath('user?id=1&name=hello#get')) //解析路径的
return (
<div>New</div>
)
}
P141 141_尚硅谷_ReactRouter6教程-总结







浙公网安备 33010602011771号