在 React.js 中,数据是从上自下流动(传递)的,也就是一个父组件可以把它的 state / props 通过 props 传递给它的子组件,但是子组件不能修改 props - React.js 是单向数据流,如果子组件需要修改父组件状态(数据),是通过回调函数方式来完成的。
父级向子级通信 把数据添加子组件的属性中,然后子组件中从props属性中,获取父级传递过来的数据
子级向父级通信 在父级中定义相关的数据操作方法(或其他回调), 把该方法传递给子级,在子级中调用该 方法父级传递消息
案例:完善好友列表
context.js:
import {createContext} from "react" let context = createContext(); let {Consumer,Provider} = context; export default context export {Consumer,Provider}所谓的生命周期就是指某个事物从开始到结束的各个阶段,当然在 React.js 中指的是组件从创建到销毁的过程,React.js 在这个过程中的不同阶段调用的函数,通过这些函数,我们可以更加精确的对组件进行控制,前面我们一直在使用的 render 函数其实就是组件生命周期渲染阶段执行的函数
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
constructor
static getDerivedStateFromProps(props, state) - 注意 this 问题(为第三个参数),需要写return
render
componentDidMount
当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
父组件更新引起组件更新 static getDerivedStateFromProps(props, state)shouldComponentUpdate()componentWillUpdate()render()getSnapshotBeforeUpdate()componentDidUpdate() 组件自身更新 shouldComponentUpdate()componentWillUpdate()render()getSnapshotBeforeUpdate()componentDidUpdate()当组件从 DOM 中移除时会调用如下方法:
componentWillUnmount当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
static getDerivedStateFromError()componentDidCatch(error, info) 参考连接:生命周期图谱1. constructor(props)
constructor(props)类的构造函数,也是组件初始化函数,一般情况下,我们会在这个阶段做 一些初始化的工作
通过给 this.state 赋值对象来初始化内部 state。处理事件绑定函数的 this。为事件处理函数绑定实例在 constructor() 函数中不要调用 setState() 方法。如果你的组件需要使用内部 state,请直接在构造函数中为 this.state 赋值初始 state:
constructor(props) { super(props); // 不要在这里调用 this.setState() this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); }只能在构造函数中直接为 this.state 赋值。如需在其他方法中赋值,你应使用 this.setState() 替代。
2. render()
render()render 方法是 Class 组件必须实现的方法
render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。如需与浏览器进行交互,请在 componentDidMount() 或其他生命周期方法中执行你的操作。保持 render() 为纯函数,可以使组件更容易思考。注意 如果 shouldComponentUpdate()返回 false,则不会调用 render()。3. static getDerivedStateFromProps(props, state) (不常用)
static getDerivedStateFromProps(props, state)该方法会在 render 方法之前调用,无论是挂载阶段还是更新阶段,它的存在只有一个目的:让组件在 props 变化时更新 state
4. componentDidMount()
componentDidMount()在组件挂载后(render 的内容插入 DOM 树中)调用。通常在这个阶段,我们可以:
操作 DOM 节点发送请求5. shouldComponentUpdate(nextProps, nextState) (不常用)
shouldComponentUpdate(nextProps, nextState)发生在更新阶段,getDerivedStateFromProps 之后,render 之前,该函数会返回一个布尔值,决定了后续是否执行 render,首次渲染不会调用该函数
6. getSnapshotBeforeUpdate(prevProps, prevState) (不常用)
getSnapshotBeforeUpdate(prevProps, prevState)render --> 虚拟DOM --> 真实DOM --> 挂载到文档 该方法在 render() 之后,但是在输出到 DOM 之前执行,用来获取渲染之前的快照。 当我们想在当前一次更新前获取上次的 DOM 状态,可以在这里进行处理,该函数的返回值将作为参数传递给下个生命周期函数componentDidUpdate
该函数并不常用。
7. componentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot)该函数会在 DOM 更新后立即调用,首次渲染不会调用该方法。我们可以在这个函数中对渲染后的 DOM 进行操作
componentDidUpdate(prevProps) { // 典型用法(不要忘记比较 props): if (this.props.userID !== prevProps.userID) { this.fetchData(this.props.userID); } }8. componentWillUnmount()
componentWillUnmount() 该方法会在组件卸载及销毁前调用,我们可以在这里做一些清理工作,如:组件内的定时器、未完成的请求等componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。9. 错误处理
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法
static getDerivedStateFromError()componentDidCatch()受控组件:类似于Vue的双向数据绑定,数据和视图之间可以相互影响 非受控组件:类似于单向数据流,只可以数据改变视图,我们不需要同步 value 值(defaultValue,defaultChecked)
import React,{Component} from 'react'; /* 受控组件 defaultValue : 非受控 */ class App extends Component { state = { info:"这是值" } render(){ let {info} = this.state; return ( <div> {/* 单向绑定 */} {/* <input type="text" defaultValue={info} /> <input type="text" defaultValue={info} /> <input type="text" defaultValue={info} /> */} {/* 受控组件:类似于Vue的双向数据绑定 数据和视图之间可以相互影响 非受控组件:类似于单向数据流 只可以数据改变视图 */} <input type="text" value={info} onChange={({target})=>{ this.setState({ info:target.value }) }} /> <button onClick={()=>{ console.log(info); }}>点一点</button> </div>) } } export default App;掌握React其他 API 使用:PureComponent、ref、children、dangerouslySetInnerHTML、key 掌握函数式组件及常见 hooks 的使用 可以独立开发基于Hooks 或 Component 的 todoList 应用