组件通信
- 父传子:props传数据
- 子传父:父组件定义回调函数,传给子组件,子组件调用,
- 兄弟通信:将公共数据交给最新的父组件管理(状态提升)
context组件的作用
跨组件传递数据,如果两个组件跨很多层级,可以使用context通信 使用:
- 使用createContext创建两个组件
const {Provider,consumer}=React.createContext()
- 父组件节点用Provide组件(提供数据)
- 父组件设置value属性,表示要传递的数据
<Provider value="pink">
- 调用Consumer组件接受数据
<Consumer>{data=><span>data表示接受的数据:{data} </span> }</Consumer>
Props深入
children属性
- ①当组件有子节点,那么props就有children属性
- ②children属性和普通的props不同,它可以任意值(文本,元素,组件,甚至函数)
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">Welcome</h1>
<p className="Dialog-message">Thank you for visiting !</p>
</FancyBorder>
);
}
组合与继承
组合:使用一个特殊的 children prop 来将他们的子组件传递到渲染结果中,别的组件可以通过 JSX 嵌套,将任意组件作为子组件传递给它们。
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children} </div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder>
);
}
继承:如果想要在组件间复用非 UI 的功能,建议将其提取为一个单独的 JavaScript 模块,如函数、对象或者类。组件可以直接引入(import)而无需通过 extend 继承它们。
Props检验
提高组件健康性,类似vue 步骤:
- ①安装prop-types包(npm i prop-types)
- ②导入包(import propTypes from "prop-type")
- ③使用组件名.propType={}方式添加检验规则
- ④检验规则通过propType来指定
// 组件.propTypes={属性: propType.类型}
Child.propTypes = {
属性: PropTypes.string.isRequired
}
Child.defaultProps= {
属性: 默认值
}
约束规则:
- ①常见类型:array func bool number string object
- ②元素类型:element
- ③必填项:isRequired
- ④特定结构对象 shape({})
props默认值:defaultProps 组件.defaultProps={属性:默认值}
组件的生命周期
- 创建时:①constructor②render③componentDidMount
- 更新时(setState,forceUpdate或者props发生更新):①render②componentDidUpdate
- 卸载时:①componentWillUnmount 注意:①render中不要调用setState②componentDidUpdate中调用setState一定要加if判断,通过参数preProps比较两次props是否相同,否则会造成死递归
组件复用:render-props以及HOC(高阶组件)
步骤:
- ①组件内提供复用的状态逻辑代码
- ②复用状态作为props.render(state)暴露到外部
- ③使用props.render作为要渲染的返回值 注意:并不是该模式叫render-props就一定要用render,只是为了告诉组件渲染props传来的函数,才叫做props.render模式,推荐使用children (this.props.children)
示范练习代码
组件复用:code.juejin.cn/api/raw/721…
setState说明:
- ①推荐使用回调函数(保证每次调用的state和props都是最新的,但是该写法还是异步的)
- ②第二个参数-回调函数(在状态更新后立即执行某个操作)
- 组件更新机制:父组件重新渲染时也会重新渲染子组件
组件性能优化
- ①减轻state:state只存储和组件渲染相关的数据,而对于和渲染无关的数据可以存在 this中,比如定时器的id
- ②避免不必要的渲染(因为父组件更新会导致子组件也更新),我们可以通过shouldComponentUpdate这个钩子函数决定子组件是否需要重新渲染 shouldComponentUpdate(nextProps,nextState){ 根据条件确定是false还是true return false//表示不用重新渲染,这样是写死了,一般应该是条件} 该函数的执行时机:更新的render之前
路由基础
- 使用步骤:
- ①安装react-router-dom
- ②导入三个路由的核心插件 import{BrowerRouter as router,Route,Link}from "react-router-dom"
- ③使用Router包裹整个应用(重要)
- ④使用Link作为导航菜单(路由入口)
两种导航模式
声明式导航
<Link to="路由路径"/>
编程式导航:
①props.history.push(路径)②props.gistory.go(-1)
路由接收参数:this.props.match.params
路由的执行过程
- ①点击Link组件(被转为a标签),修改了浏览器地址的url
- ②react路由监听地址栏url的变化
- ③react路由内部遍历所有Route组件,使用路由规则path与pathname做匹配
- ④当path与pathname匹配成功后就展示该Route组件内容
默认路由:
表示进去页面就会匹配的路由,路径为"/"
总结:
- ①路由可以有效管理多个视图(组件),实现SPA
- ②react组件包裹整个应用,只需使用一次
- ③Link是入口,Route是出口
- ④通过props.history.push()实现路由跳转
- ⑤默认模糊匹配,添加exact属性变成精准匹配