哪个网站做照片书最好看,网站建设好卖吗,建设交流网站,暗网是什么网站目录#xff1a;
扩展1_setState扩展2_lazyLoad扩展3_stateHook扩展4_EffectHook扩展5_RefHook扩展6_Fragment扩展7_Context扩展8_PureComponent扩展9_renderProps扩展10_ErrorBoundary组件通信方式总结
1.扩展1_setState
setState更新状态的2种写法
setState(stateChange…目录
扩展1_setState扩展2_lazyLoad扩展3_stateHook扩展4_EffectHook扩展5_RefHook扩展6_Fragment扩展7_Context扩展8_PureComponent扩展9_renderProps扩展10_ErrorBoundary组件通信方式总结
1.扩展1_setState
setState更新状态的2种写法
setState(stateChange, [callback])------对象式的setState 1.stateChange为状态改变对象(该对象可以体现出状态的更改)2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用setState(updater, [callback])------函数式的setState 1.updater为返回stateChange对象的函数。2.updater可以接收到state和props。3.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。总结:1.对象式的setState是函数式的setState的简写方式(语法糖)2.使用原则 (1).如果新状态不依赖于原状态 使用对象方式(2).如果新状态依赖于原状态 使用函数方式(3).如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取
Demo.jsx
import React, {Component} from react;class Demo extends Component {state {count: 0}add () {//对象式的setState// const {count} this.state// this.setState({count: count 1}, () {// console.log(this.state.count)// })// // console.log(12行的输出, this.state.count)//函数式的setState// this.setState((state, props) {// console.log(state, props)// return {count: state.count 1}// })this.setState(state ({count: state.count 1}), () {console.log(this.state.count)})// this.setState({count: this.state.count 1})}render() {return (divh1当前求和为{this.state.count}/h1button onClick{this.add}点我1/button/div);}
}export default Demo; 2.扩展2_lazyLoad
路由组件的lazyLoad
//1.通过React的lazy函数配合import()函数动态加载路由组件 路由组件代码会被分开打包const Login lazy(()import(/pages/Login))//2.通过Suspense指定在加载得到路由打包文件前显示一个自定义loading界面Suspense fallback{h1loading...../h1}SwitchRoute path/xxx component{Xxxx}/Redirect to/login//Switch/Suspense
About.jsx
import React, {Component} from react;class About extends Component {render() {return (divh3我是About的内容/h3/div);}
}export default About;
Demo.jsx
import React, {Component, lazy, Suspense} from react;
import {NavLink, Route} from react-router-dom;
import Loading from ../Loading/Loading;const Home lazy(() import(../Home/Home))
const About lazy(() import(../About/About))class Demo extends Component {render() {return (divdiv classNamerowdiv classNamecol-xs-offset-2 col-xs-8div classNamepage-headerh2React Router Demo/h2/div/div/divdiv classNamerowdiv classNamecol-xs-2 col-xs-offset-2div classNamelist-groupNavLink classNamelist-group-item to/aboutAbout/NavLinkNavLink classNamelist-group-item to/homeHome/NavLink/div/divdiv classNamecol-xs-6div classNamepaneldiv classNamepanel-bodySuspense fallback{Loading/Loading}Route path/about component{About}/RouteRoute path/home component{Home}/Route/Suspense/div/div/div/div/div);}
}export default Demo;
Home.jsx
import React, {Component} from react;class Home extends Component {render() {return (divh3我是Home的内容/h3/div);}
}export default Home;
Loading.jsx
import React, {Component} from react;class Loading extends Component {render() {return (divh1 style{{backgroundColor: gray, color: orange}}Loading/h1/div);}
}export default Loading;
App.js
import React, {Component} from react;
import Demo from ./components/Demo/Demo;class App extends Component {render() {return (divDemo/Demo/div);}
}export default App;
index.js
import React from react;
import ReactDOM from react-dom/client;
import App from ./App;
import {BrowserRouter} from react-router-dom;const root ReactDOM.createRoot(document.getElementById(root));root.render(BrowserRouterApp//BrowserRouter
);3.扩展3_stateHook React Hook/Hooks是什么?
Hook是React 16.8.0版本增加的新特性/新语法可以让你在函数组件中使用 state 以及其他的 React 特性
三个常用的Hook
State Hook: React.useState()Effect Hook: React.useEffect()Ref Hook: React.useRef()
State Hook
State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作语法: const [xxx, setXxx] React.useState(initValue) useState()说明: 参数: 第一次初始化指定的值在内部作缓存返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数setXxx()2种写法: setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值setXxx(value newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值 Demo.jsx
import React, {Component} from react;// class Demo extends Component {
// state {count: 0}
//
// add () {
// this.setState(state ({count: state.count 1}))
// }
//
// render() {
// return (
// div
// h2当前求和为{this.state.count}/h2
// button onClick{this.add}点我1/button
// /div
// );
// }
// }function Demo() {const [count, setCount] React.useState(0)const [name, setName] React.useState(tom)function add() {// setCount(count 1)setCount((count) {return count 1})}function changeName() {// setName(jack)setName((name) {return jack})}return (divh2当前求和为{count}/h2h2我的名字是{name}/h2button onClick{add}点我1/buttonbutton onClick{changeName}点我改名/button/div)
}export default Demo;
4.扩展4_EffectHook
Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)React中的副作用操作: 发ajax请求数据获取设置订阅 / 启动定时器手动更改真实DOM 语法和说明: useEffect(() { // 在此可以执行任何带副作用操作return () { // 在组件卸载前执行// 在此做一些收尾工作, 比如清除定时器/取消订阅等}}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行可以把 useEffect Hook 看做如下三个函数的组合 componentDidMount()componentDidUpdate()componentWillUnmount() Demo.jsx
import React, {Component} from react;
import ReactDOM from react-dom;// class Demo extends Component {
// state {count: 0}
//
// add () {
// this.setState(state ({count: state.count 1}))
// }
//
// unmount () {
// ReactDOM.unmountComponentAtNode(document.getElementById(root))
// }
//
// componentDidMount() {
// this.timer setInterval(() {
// this.setState(state ({count: state.count 1}))
// }, 1000)
// }
//
// componentWillUnmount() {
// clearInterval(this.timer)
// }
//
// render() {
// return (
// div
// h2当前求和为{this.state.count}/h2
// button onClick{this.add}点我1/button
// button onClick{this.unmount}卸载组件/button
// /div
// );
// }
// }function Demo() {const [count, setCount] React.useState(0)React.useEffect(() {let timer setInterval(() {setCount(count count 1)}, 1000)return () {clearInterval(timer)}}, [])function add() {setCount(count 1)}function unmount() {ReactDOM.unmountComponentAtNode(document.getElementById(root))}return (divh2当前求和为{count}/h2button onClick{add}点我1/buttonbutton onClick{unmount}卸载组件/button/div)
}export default Demo;
5.扩展5_RefHook
Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据语法: const refContainer useRef()作用:保存标签对象,功能与React.createRef()一样
Demo.jsx
import React, {Component} from react;
import ReactDOM from react-dom;// class Demo extends Component {
// state {count: 0}
//
// myRef React.createRef()
//
// add () {
// this.setState(state ({count: state.count 1}))
// }
//
// unmount () {
// ReactDOM.unmountComponentAtNode(document.getElementById(root))
// }
//
// show () {
// alert(this.myRef.current.value)
// }
//
// componentDidMount() {
// this.timer setInterval(() {
// this.setState(state ({count: state.count 1}))
// }, 1000)
// }
//
// componentWillUnmount() {
// clearInterval(this.timer)
// }
//
// render() {
// return (
// div
// input typetext ref{this.myRef}/
// h2当前求和为{this.state.count}/h2
// button onClick{this.add}点我1/button
// button onClick{this.unmount}卸载组件/button
// button onClick{this.show}点击提示数据/button
// /div
// );
// }
// }function Demo() {const [count, setCount] React.useState(0)const myRef React.useRef()React.useEffect(() {let timer setInterval(() {setCount(count count 1)}, 1000)return () {clearInterval(timer)}}, [])function add() {setCount(count 1)}function show() {alert(myRef.current.value)}function unmount() {ReactDOM.unmountComponentAtNode(document.getElementById(root))}return (divinput typetext ref{myRef}/h2当前求和为{count}/h2button onClick{add}点我1/buttonbutton onClick{unmount}卸载组件/buttonbutton onClick{show}点我提示数据/button/div)
}export default Demo; 6.扩展6_Fragment
作用 可以不用必须有一个真实的DOM根标签了 Demo.jsx
import React, {Component, Fragment} from react;class Demo extends Component {render() {return (Fragment key{1}input typetext/input typetext//Fragment);}
}export default Demo;
7.扩展7_Context 理解 一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信 使用
创建Context容器对象 const XxxContext React.createContext() 渲染子组时外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据 xxxContext.Provider value{数据}子组件/xxxContext.Provider后代组件读取数据 //第一种方式:仅适用于类组件 static contextType xxxContext // 声明接收contextthis.context // 读取context中的value数据//第二种方式: 函数组件与类组件都可以 xxxContext.Consumer{value ( // value就是context中的value数据要显示的内容)}/xxxContext.Consumer
注意
在应用开发中一般不用context, 一般都用它的封装react插件react-redux Demo.jsx
import React, {Component} from react;
import ./Demo.cssconst MyContext React.createContext()
const {Provider, Consumer} MyContext
export default class A extends Component {state {username: tom, age: 18}render() {const {username, age} this.statereturn (div classNameparenth3我是A组件/h3h4我的用户名是{username}/h4Provider value{{username, age}}B/B/Provider/div);}
}class B extends Component {render() {return (div classNamechildh3我是B组件/h3C/C/div);}
}// class C extends Component {
// static contextType MyContext
//
// render() {
// const {username, age} this.context
// return (
// div classNamegrand
// h3我是C组件/h3
// h4我从A组件接收到的用户名{username},年龄是{age}/h4
// /div
// );
// }
// }function C() {return (div classNamegrandh3我是C组件/h3h4我从A组件接收到的用户名Consumer{value {return ${value.username},年龄是${value.age}}}/Consumer/h4/div)
}
Demo.css
.parent {width: 500px;background-color: orange;padding: 8px;
}.child {width: 100%;background-color: skyblue;padding: 8px;
}.grand {width: 100%;background-color: gray;padding: 8px;
}
8.扩展8_PureComponent
组件优化
Component的2个问题 只要执行setState(,即使不改变状态数据,组件也会重新render()只当前组件重新render(),就会自动重新render子组件效率低效率高的做法 只有当组件的state或props数据发生改变时才重新render()
原因
Component中的shouldComponentUpdate()总是返回true
解决
办法1: 重写shouldComponentUpdate()方法比较新旧state或props数据如果有变化才返回true如果没有返回false办法2:使用Pur eComponentPureComponent重写了shouldComponentUpdate()只有state或props数据有变化才返回true注意: 只是进行state和props数据的浅比较如果只是数据对象内部数据变了返回fa1se不要直接修改stat e数据而是要产生新数据项目中一般使用PureComponent来优化
办法一Demo.jsx
import React, {Component} from react;
import ./Demo.cssclass Parent extends Component {state {carName: 奔驰c36}changeCar () {this.setState({})}shouldComponentUpdate(nextProps, nextState, nextContext) {console.log(this.props, this.state, Parent)console.log(nextProps, nextState, Parent)return !this.state.carName nextState.carName}render() {console.log(Parent--render)const {carName} this.statereturn (div classNameparenth3我是Parent组件/h3span我的车名字是{carName}/spanbr/brbutton onClick{this.changeCar}点我换车/buttonChild carName{carName}/Child/div);}
}class Child extends Component {shouldComponentUpdate(nextProps, nextState, nextContext) {console.log(this.props, this.state, Child)console.log(nextState, nextState, Child)return !this.props.carName nextState.carName}render() {console.log(Child--render)return (div classNamechildh3我是Child组件/h3span我接到的车是{this.props.carName}/span/div);}
}export default Parent; Demo.css
.parent {background-color: orange;padding: 10px;
}.child {background-color: gray;margin-top: 30px;padding: 10px;
}
办法二Demo.jsx
import React, {PureComponent} from react;
import ./Demo.cssclass Parent extends PureComponent {state {carName: 奔驰c36, stus: [小张, 小李, 小王]}addStu () {// const {stus} this.state// stus.unshift(小刘)// this.setState({stus: stus})const {stus} this.statethis.setState({stus: [小刘, ...stus]})}changeCar () {// this.setState({carName: 迈巴赫})const obj this.stateobj.carName 迈巴赫console.log(obj this.state)this.setState(obj)}// shouldComponentUpdate(nextProps, nextState, nextContext) {// console.log(this.props, this.state, Parent)// console.log(nextProps, nextState, Parent)// return !this.state.carName nextState.carName// }render() {console.log(Parent--render)const {carName} this.statereturn (div classNameparenth3我是Parent组件/h3{this.state.stus}nbsp;span我的车名字是{carName}/spanbr/brbutton onClick{this.changeCar}点我换车/buttonbutton onClick{this.addStu}添加一个小刘/buttonChild carName奥拓/Child/div);}
}class Child extends PureComponent {// shouldComponentUpdate(nextProps, nextState, nextContext) {// console.log(this.props, this.state, Child)// console.log(nextState, nextState, Child)// return !this.props.carName nextState.carName// }render() {console.log(Child--render)return (div classNamechildh3我是Child组件/h3span我接到的车是{this.props.carName}/span/div);}
}export default Parent;
9.扩展9_renderProps
如何向组件内部动态传入带内容的结构(标签)?
vue中: 使用slot技术也就是通过组件标签体传入结构AB//AReact中: 使用children props:通过组件标签体传入结构使用render props:通过组件标签属性传入结构一般用render函数属性
children props
A BXXXX/B/A{this.props.children}问题:如果B组件需要A组件内的数据做不到
render props
A render{(data) C data{data}/C}/AA组件: {this.props.render (内部state数据)}c组件:读取A组件传入的数据显示 {this.props.data}
Demo.jsx
import React, {Component} from react;
import ./Demo.cssclass Parent extends Component {render() {return (div classNameparenth3我是Parent组件/h3A render{(name) B name{name}/B}/A/div);}
}class A extends Component {state {name: tom}render() {const {name} this.statereturn (div classNameah3我是A组件/h3{this.props.render(name)}/div)}
}class B extends Component {render() {return (div classNamebh3我是B组件,{this.props.name}/h3/div)}
}export default Parent; Demo.css
.parent {background-color: orange;padding: 10px;
}.a {background-color: gray;margin-top: 30px;padding: 10px;
}.b {background-color: skyblue;margin-top: 30px;padding: 10px;
} 10.扩展10_ErrorBoundary
理解:
错误边界(Error bojundary):用来捕获后代组件错误渲染出备用页面
特点:
只能捕获后代组件生命周期产生的错误不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
使用方式:
getDerivedStateFromError配合componentDidCatch
// 生命周期函数一旦后代组件报错就会触发
static getDerivedStateFromError(error) {console.log(error);// 在render之前触发// 返回新的statereturn {hasError: true,};
}componentDidCatch(error, info) {// 统计页面的错误。发送请求发送到后台去console.log(error, info);
}
Parent.jsx
import React, {Component} from react;
import Child from ./Child;class Parent extends Component {state {hasError: }//当Parent的子组件出现报错时候会触发getDerivedStateFromError调用并携带错误信息static getDerivedStateFromError(error) {console.log(error)return {hasError: error}}componentDidCatch(error, errorInfo) {console.log(渲染组件时出错)}render() {return (divh2我是Parent组件/h2{this.state.hasError ? h2当前网络不稳定稍后再试/h2 : Child/Child}/div);}
}export default Parent;
Child.jsx
import React, {Component} from react;class Child extends Component {state {// users: [// {id: 001, name: tom, age: 18},// {id: 002, name: jack, age: 19},// {id: 003, name: peiqi, age: 20},// ]users: abc}render() {return (divh2我是Child组件/h2{this.state.users.map((userObj) {return h4 key{userObj.id}{userObj.name}-----{userObj.age}/h4})}/div);}
}export default Child;
11.组件通信方式总结
组件间的关系
父子组件兄弟组件非嵌套组件祖孙组件跨级组件
几种通信方式 1.props(1).children props(2).render props2.消息订阅-发布pubs-sub、event等等3.集中式管理redux、dva等等4.conText:生产者-消费者模式 比较好的搭配方式
父子组件props兄弟组件消息订阅-发布、集中式管理祖孙组件(跨级组件)消息订阅-发布、集中式管理、conText(开发用的少封装插件用的多)