极品-------React的组件通信,生命周期,受控组件,与非受控组件

Posted 哈比老乌龟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了极品-------React的组件通信,生命周期,受控组件,与非受控组件相关的知识,希望对你有一定的参考价值。

React中的主要的组件通信有
一.父传子
二.子传父
三.兄弟相传

一.父传子

父组件传递数据给子组件
1.父组件中引入子组件

import Family from "./family";

2.在父组件中使用子组件

  <Family/>

3.父组件提供要传递的state数据

  state = {
    Lastname:"火娃",
  }

4.给子组件标签添加属性.值为state中的数据

  <Family name={this.state.Lastname}/>

5.子组件中通过props接受父组件中传递的数据

 <li>{this.props.name}</li>

父组件

class App extends Component{
  state = {
    hEight:174,
    tex:'',
    Lastname:"火娃",
    shu:0
  }
  render(){
    return (<div>
        <Family name={this.state.Lastname}/>
    </div>)
  }
}

子组件

class Family extends React.Component{
    render(){
      return  (<div>
            <ul>  
                <li>{this.props.name}</li>
            </ul>
        </div>)
    }
};
ReactDOM.render(<Family/>,
document.querySelector('#root'))
export default Family

二.子传父

子传父,父组件提供一个方法,把方法传给子组件,子组件调用传参,这是回调函数
1.提供方法

 Child = props =>{
    return(
      <div>
        <p>{props.name}</p>
      </div>
    )
  }

2.传给子组件

  <Family  getMsg={this.Child} }/> 

3.子组件调用

 dianclick=()=>{
        this.props.getMsg(this.state.msg)
    }

4.传入子组件的数据

  state={
        msg:'水娃'
    }
    dianclick=()=>{
        this.props.getMsg(this.state.msg)
    }

父组件

class App extends Component{
  state = {
    hEight:174,
    tex:'',
    Lastname:"火娃",
    shu:0
  }
  getChild=(data)=>{
    console.log(data)
  }
  Child = props =>{
    return(
      <div>
        <p>{props.name}</p>
      </div>
    )
  }
  render(){
    // let {hEight} = this.state
    return (<div>
        <Family  getMsg={this.Child} }/> 
  }
};

子组件

class Family extends React.Component{
    state={
        msg:'水娃'
    }
    dianclick=()=>{
        this.props.getMsg(this.state.msg)
    }
    render(){
      return  (<div>
            <ul>
                <li>{this.props.name}</li>
                <li>{this.props.shu}</li>
            </ul>
        </div>)
    }
};
ReactDOM.render(<Family/>,
document.querySelector('#root'))
export default Family

三.兄弟组件传参

React组件通信中兄弟传参需要媒介,他们共同的父组件该变父组件中的而改变子组件的
1.在父组件中定义方法

  onIncrement = ()=>{
    this.setState({
      shu:this.state.shu+1
    })
  }

2.在父组件中定义属性

 state = {
    shu:0
  }

3.传给子组件

 <Family  shu={this.state.shu}/>
 <Parent onIncrement={this.onIncrement}/>

4.子组件中使用

第一个子组件
  <li>{this.props.shu}</li>
第二个子组件 
 <button onClick={()=>this.props.onIncrement()}>+1</button>

父组件

class App extends Component{
  state = {
    shu:0
  }
  getChild=(data)=>{
    console.log(data)
  }
  onIncrement = ()=>{
    this.setState({
      shu:this.state.shu+1
    })
  }
  render(){
    // let {hEight} = this.state
    return (<div>
        <Family  shu={this.state.shu}/>
        <Parent onIncrement={this.onIncrement}/>
    </div>)
  }
};

第一个子组件

import React from "react";
import ReactDOM from "react-dom";

class Family extends React.Component{
    state={
        msg:'水娃'
    }
    // Child = props=>{
    //     return (
    //         <div>
    //             <p>{props.Lastname}</p>
    //         </div>
    //     )
    // }
    dianclick=()=>{
        this.props.getMsg(this.state.msg)
    }
    render(){
      return  (<div>
           {/* <button onClick={this.Child()}>父传子</button> */}
            <ul>
                <li>one</li>
                <li>two</li>
                <li>three</li>
                <li>{this.props.name}</li>
                <li>{this.props.shu}</li>
            </ul>
            <button onClick={this.dianclick}>点击葫芦娃</button>
        </div>)
    }
};
ReactDOM.render(<Family/>,
document.querySelector('#root'))
export default Family

第二个子组件

import React from "react"
import Boy from "./boy"
class Parent extends React.Component{
    render(){
        return(
            <div>
                <Boy />
                <p>我是二组件</p>
                <button onClick={()=>this.props.onIncrement()}>+1</button>
            </div>
        )
    }
}
export default Parent

跨组件传参

const {Provider,Consumer} = React.createContext()
class App extends Component{
  render(){
    return (<div> 
    	//创建
        <Provider value="孙子嘿嘿">
        <Parent onIncrement={this.onIncrement}/>
        </Provider>
    </div>)
  }
};
//消耗
 <Consumer>
         {data => <p>我是孙子{data}</p>}
 </Consumer>

五.受控组件与非受控组件

解释:
html 中,表单元素(如input、 textarea 和 select)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
见解:
每当输入框的输入内容发生变化时,都会被写入到组件的state中,这种组件在React中被理解为受控组件。
受控组件的值,始终是由React的state驱动的。
这种组件的数据是由React组件进行管理的,所以在大多数情况下,官方推荐使用受控组件。

受控组件

import React, { Component, Fragment } from 'react'
export default class Demohooks extends Component {
  constructor(props) {
    super(props);
    this.state = {
      controllValue: 0,
    }
  }
  onChangeInput = (e) => {
    this.setState({
      controllValue: e.target.value
    })
  }
  render() {
    return (
      <Fragment>
        <h1>受控组件</h1>
        <div>{this.state.controllValue}</div>
        用户名:<input value={null} onChange={this.onChangeInput} />
      </Fragment>
    )
  }
}

非受控组件
官网:
要编写一个非受控组件,而不是为每个状态更新都编写数据处理函数,你可以使用 ref来从 DOM 节点中获取表单数据。
因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。

总的来说就是操作DOM节点,所以官方推荐受控组件
非受控组件

import React, { Component } from 'react'

export default class Demohooks extends Component {
  onSubmit = (event) => {
    event.preventDefault();
    const { inputName, password } = this;
    console.log(inputName.value)
    console.log(password.value)
  }
  render() {
    return (
      <div>
        <form onSubmit={this.onSubmit}>
          用户名:<input ref={c => this.inputName = c} /> <br />
          密码:<input ref={c => this.password = c} /> <br />
          <button>登录</button>
        </form>
      </div>
    )
  }
}

React生命周期

生命周期的方法有:
constructor()
constructor()中完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。
注意:只要使用了constructor()就必须写super(),否则会导致this指向错误。

componentWillMount()
componentWillMount()一般用的比较少,它更多的是在服务端渲染时使用。它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。

componentDidMount()
组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染

componentWillUnmount ()
在此处完成组件的卸载和数据的销毁。

componentWillReceiveProps (nextProps)
在接受父组件改变后的props需要重新渲染组件时用到的比较多
接受一个参数nextProps
通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件

shouldComponentUpdate(nextProps,nextState)
主要用于性能优化(部分更新)
唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新
因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断
componentWillUpdate (nextProps,nextState)
shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。

componentDidUpdate(prevProps,prevState)
组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。

render()
render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

getDerivedStateFromProps(nextProps, prevState)
代替componentWillReceiveProps()。
老版本中的componentWillReceiveProps()方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数
getSnapshotBeforeUpdate(prevProps, prevState)
代替componentWillUpdate。
常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。
这两者的区别在于:

在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在
componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。
此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。

以上是关于极品-------React的组件通信,生命周期,受控组件,与非受控组件的主要内容,如果未能解决你的问题,请参考以下文章

极品-------React的组件通信,生命周期,受控组件,与非受控组件

极品-------React的组件通信,生命周期,受控组件,与非受控组件

极品-React生命周期详情,hooks

极品-React生命周期详情,hooks

极品-React生命周期详情,hooks

极品-React生命周期详情,hooks