1.react生命周期
react生命周期:很多的事物从创建到销毁的整个过程,这个过程被称之为声明周期
React组件也有自己的生命周期,了解组件的生命周期可以让我们在最合适的地方完成自己想要的功能;
- 生命周期和生命周期函数的关系:
生命周期是一个抽象的概念 ,在生命周期的整个过程,分成了很多个阶段;
1.比如装载阶段( Mount), 组件第一次在DOM树中被渲染的过程 ;
2.比如更新过程( Update ), 组件状态发生变化,重新更新渲染的过程;
3.比如卸载过程( Unmount) , 组件从DOM树中被移除的过程; - React内部为了告诉我们当前处于哪些阶段,会对我们组件内部实现的某些函数进行回调,这些函数就是生命周期函数:
1.比如实现componentDidMount函数:组件已经挂载到DOM上时,就会回调;
2.比如实现componentDidUpdate函数 :组件已经发生了更新时,就会回调;
3.比如实现componentWillUnmount函数 :组件即将被移除时,就会回调;
我们可以在这些回调函数中编写自己的逻辑代码,来完成自己的需求功能; - 我们谈React生命周期时,主要谈的类的生命周期,因为函数式组件是没有生命周期函数的; (后面我们可以通过hooks来模拟一些生命周期的回调)
2.react生命周期解析
import React, { Component } from 'react'
class Cpn extends Component {
render(){
return (
<div>
我是cpn组件
</div>
)
}
componentWillUnmount(){
console.log('执行了cpn组件的componentWillUnmount方法')
}
}
export default class App extends Component {
constructor(){
super();
console.log('执行了组件的constructor方法')
this.state = {
count:0,
isShow:true
}
}
render() {
console.log('执行了组件的render方法')
return (
<div>
我是app组件
<h2>当前计数:{this.state.count}</h2>
<button onClick={e => this.increment()}>+1</button>
<button onClick={e => this.change()}>切换</button>
{this.state.isShow && <Cpn/>}
</div>
)
}
componentDidMount(){
console.log('执行了组件的componentDidMount方法')
}
componentDidUpdate(){
console.log('执行了组件的componentDidUpdate方法')
}
increment(){
this.setState({
count:this.state.count + 1
})
}
change(){
this.setState({
isShow:!this.state.isShow
})
}
}
3.通常在生命周期中干什么?
-
Constructor
如果不初始化state或者不进行方法绑定,则不需要为React组件实现构造函数。
construcotr中通常会作两件事情:- 通过this.state赋值对象来初始化内部的state
- 为事件绑定实例(this)
-
componentDidMount
componentDidMount()通常会在组件挂载后立即调用
componentDidMount()中通常会作两件事情:- 依赖于DOM的操作可以在这里进行
- 在此处发送网络请求就是最好的地方
- 可以在此处添加一些订阅(在componentWillUnmount取消订阅)
-
componentDidUpdate
componentDidUpdate()会在更新后会被立即调用,首次渲染不会执行此方法。
componentDidUpdate()中通常会作两件事情:- 当组件更新后,可以在此处对DOM进行操作;
- 如果你对更新前后的props进行了比较,也可以选择在此处进行网络请求; ( 例如,当props未发生变化时,则不会执行网络请求)。
-
componentWillUnmount
componentWillUnmount()会在组件卸载及销毁之前直接调用。
componentWillUnmount()中通常会作这些事情:- 在此方法中执行必要的清理操作;
- 例如,清除timer ,取消网络请求或清除
- 在componentDidMount()中创建的订阅等;
react组件间的通信
1.组件之间存在嵌套关系:
- 在之前的案例中,我们只是创建了一个组件App ;
- 如果我们一个应用程序将所有的逻辑都放在一个组件中,那么这个组件就会变成非常的臃肿和难以维护;
- 所以组件化的核心思想应该是对组件进行拆分,拆分成一个个小的组件;
- 再将这些组件组合嵌套在一起,最终形成我们的应用程序;
import React, {
Component } from 'react'
// Header
function Header(){
return (
<h2>我是header组件</h2>
)
}
// Main
function Main(){
return (
<div>
<Banner/>
<ProductList/>
</div>
)
}
//banner
function Banner(){
return (
<h2>我是Banner组件</h2>
)
}
//productList
function ProductList(){
return (
<div>
<ul>
<li>商品列表1</li>
<li>商品列表2</li>
<li>商品列表3</li>
<li>商品列表4</li>
<li>商品列表5</li>
</ul>
</div>
)
}
// Footer
function Footer(){
return (
<h2>我是Footer组件</h2>
)
}
export default class App extends Component {
render() {
return (
<div>
<Header/>
<Main/>
<Footer/>
</div>
)
}
}
2.父子组件之间的通信:
-
在开发过程中,我们会经常遇到需要组件之间相互进行通信:
1.比如App可能使用了多个Header ,每个地方的Header展示的内容不同,那么我们就需要使用者传递给Header-些数据,让其进行展示;
2.又比如我们在Main中一次性请求 了Banner数据和ProductList数据,那么就需要传递给他们来进行展示;
3.也可能是子组件中发生了事件,需要由父组件来完成某些操作,那就需要子组件向父组件传递事件; -
总之,在一个React项目中,组件之间的通信是非常重要的环节;
父组件在展示子组件,可能会传递一些数据给子组件:
父组件通过属性=值的形式来传递给子组件数据;
子组件通过props参数获取父组件传递过来的数据;
3.父组件传递数据给子组件 - 类组件
//父传子 类组件
class ChildCpn extends Component {
render(){
const {
name , password} = this.props.data;
return (
<h2>子组件展示数据:{
name + password}</h2>
)
}
}
export default class App extends Component {
constructor(){
super()
this.state = {
data:{
name:'admin',
password:'123456'
}
}
}
render() {
return (
<div>
<ChildCpn data = {
this.state.data}/>
</div>
)
}
}
4.父组件传递数据给子组件 - 函数组件
//父传子 函数组件
function ChildCpn(props){
const {
name, password} = props.data;
return (
<div>
<h2>姓名:{
name} 密码: {
password}`</h2>
</div>
)
}
export default class App extends Component {
constructor(){
super()
this.state = {
data:{
name:'admin',
password:'123456'
}
}
}
render() {
return (
<div>
<ChildCpn data = {
this.state.data}/>
</div>
)
}
}
5.参数传递 --参数属性验证
- 对于传递给子组件的数据,有时候我们可能希望进行验证,特别是对于大型项目来说:
1.当然,如果你项目中默认继承了Flow或者TypeScript,那么直接就可以进行类型验证;
2.但是,即使我们没有使用Flow或者TypeScript ,也可以通过prop-types库来进行参数验证;
import React, {
Component } from 'react'
//参数类型校验
import PropTypes from 'prop-types'
//父传子 函数组件
function ChildCpn(props){
console.log(props)
let personList = props.data;
return (
<div>
<ul>
{
personList.map((item,index) => {
return <li>{
item.name} : {
item.password} </li>
})
}
</ul>
</div>
)
}
//我们需要data类型为array类型
ChildCpn.propTypes = {
data:PropTypes.array
}
//属性默认值 父组件传递数据为空
ChildCpn.defaultProps = {
data:[
{
name:'暂无数据',password:'xxxxxx'}
]
}
export default class App extends Component {
constructor(){
super()
this.state = {
data:[
{
name:'zhangsan',password:'123456'},
{
name:'lisi',password:'abcdef'},
{
name:'wangwu',password:'777777'}
]
}
}
render() {
return (
<div>
<ChildCpn data = {
this.state.data}/>
</div>
)
}
}