1,关于纯函数的概念总结
函数的目的是为了解决一些计算逻辑,通过入参传递计算所需的变量,出参导出计算结果。如果已知函数内部的处理逻辑,通过入参,就可以知道出参的结果,就可以称之为一个纯函数。
纯函数的出现,是为了保护函数内部逻辑和外部不产生耦合,纯函数的可复用性更高,可以减少整体代码的复杂性和出错概率。
例如:
const add = (a,b) => a + b (纯函数)
{
let c = 1
const add = (a,b) => a + b + c (依赖外部变量不是一个纯函数)
}
2,React context
React 提供 React.createContext() 方法返回 Object
const DarkContext = React.createContext('dark')
DarkContext .Provider 提供组件传递到下一层的每一个组件中
<DarkContext.Provider value="white">
<Card></Card>
</DarkContext>
class Card extends React.Component {
static contextType = DarkContext
render(){
<div>{this.context}</div>
}
}
优点:createContent 可用于全局信息设置,例如用户信息等。props传递适用于一些层级之间的信息传递。
缺点:createContent使用不对会造成资源传递浪费
如果组件中不需要每一层都要接受这个context,就会有资源浪费,可以将所需要参数的组件在接收参数后,再将自身通过参数的方式传递到所需的地方
const Main= (props) =>{
let titleSolt = (<Title text={props.title}></Title>)
return(
<Card title={titleSolt }></Card>
)
}
优点:减少值传递的资源浪费。
缺点:props传递使用不对会加重组件的逻辑处理。
DarkContext.Consumer 提供一个回调函数接收返回值
<DarkContext.Consumer>
{value =>...}
</DarkContext.Consumer>
3,React Lazy (组件加载)
import { Suspense } form 'React'
let Card = React.lazy('./card.js')
<Suspense fallback={<div>loading</div>}>
<Card/>
</Suspense>
<Suspense fallback={<div>loading</div>}>
<Route path="/" component={Card} ></Route>
</Suspense>
4,React 错误组件捕获
let ErrorDomFn = () => { return ( <div>errorDom</div> ) }const errorFn = (errFn = null,ErrorDom = '') =>{ return class extends React.Component { constructor(props){ super(props) this.state = {error:false} } static getDerivedStateFromError(error){ return { error: true }; } componentDidCatch(error,errorInfo){ if(errFn && errFn instanceof Function){ errFn(error,errorInfo) return; } console.log(error,errorInfo) } render(){ if(this.state.error){ return <ErrorDom/> || <div>error</div> } return this.props.children; } } }
let ErrorContent = errorFn(null,ErrorDomFn)
5,React ref
通过 React.createRef() 创建 ref ,子组件(只包含类组件)或者dom元素通过ref属性接收创建的变量,在组件挂载到页面时把当前节点信息返回
let createContent = (Comment) =>{ class MainContent extends React.Component{constructor(props){ super(props) }
componentDidMount(){
}
render(){ const {commentRef,...rest} = this.props return <Comment {...rest} ref={commentRef}/> }
}
return React.forwardRef((props,ref)=>{ return <MainContent {...props} commentRef = {ref}/> }) } class CardBox extends React.Component{ constructor(props){ super(props) } render(){ return <div>cardBox</div> } } let MainContent = createContent(CardBox)
class Card extends React.Component{ commentRef = React.createRef() constructor(props){ super(props) } componentDidMount(){ console.log(this.commentRef,'commentRef') } render(){ return <MainContent ref={this.commentRef}/> } }
6,React Fragments
let TableList = (props)=>{return ( <table> <tbody> <tr> { props.list.map((item,index)=>( <React.Fragment key={index}> <th>{item.title}</th> <th>{item.text}</th> </React.Fragment> )) } </tr> </tbody> </table> ) }
7,React 高阶函数
1,关于横切面的一些理解
指的是在代码业务中,纵向处理逻辑相同,但是业务逻辑中所使用的参数或者方法不相同。
原理是利用函数参数将组件的props传递出来,进行操作,返回结果给组件
例如:从后台获取数据过滤功能到组件
let getData = (handlerData,Component)=>{
return class extends React.component{
constructor(props){
super(props)
this.state = {data:handlerData(props)}
this.getApiData = this.getApiData.bind(this)
}
componentDidMount(){
this.getApiData()
}
getApiData(){
this.state = {data:handlerData(this.props)}
}
render(){
<Compontent data={this.state.data} />
}
}
}
2,修改原来的类组件,可以使用函数增强类组件,不建议直接修改原型.
例如:判断是否更新组件 componentDidupdate
function logProps(WrappedComponent){
return class extends React.component {
componentDidupdate(prevProps){
if(this.props.flag === prevProps.flag){
console.log('可以写一些数据操作')
}
}
render(){
<WrappedComponent/>
}
}
}
3,React 中render不可以重复调用HOC生成组件,会无法判断组件和上一个组件相等,从而卸载上一个组件
4,使用React HOC 重新创建类组件,如果想使用参数组件上的静态方法,需要组件手动赋值或者调用工具函数实现
5,ref 不作为 props 属性传递,可以使用forwardRef函数把ref赋值给props进行传递
8,关于React结合第三方库的使用
1,可以通过el等元素,赋值给第三方库进行dom操作。减少组件props以免影响dom的更新,可以结合React生命周期函数选择dom触发时机 2,ReactDom.render('组件','组件要挂载的节点对象') 渲染到对应的容器里 3,可以使用高阶组件封装第三方数据逻辑,将数据通过state props 传递到下一个组件9,关于React JSX 语法
1,jsx 本身是 React.CreateElement 语法简写,任何JSX语法最终都会调用 React.createElement 进行转换 React.CreateElement (dom节点,{color:black},'内容')
2,jsx使用文件必须导入 import React from 'react'
3,jsx 组件命名必须大写开头,可以使用点语法 obj= {Box :function(){ return <div>11</div>}} 不能使用obj[Box] 语法
4,jsx props 包括标签之间可以是一个表达式,标签之间可以使用 this.props.childern 来获取节点内部的信息,props可以使用es6表达式{...otherProps}传递属性
补充:props 是一个表达式可以将值传递到下一层的组件中,可以通过传递函数的方式渲染不同的组件,解决横切面的问题,props函数的值如果是匿名函数props认为每次都是
不同的值,可以声明一个命名函数就不会有这样的问题,具体 React.PureComponent 会出现这种情况
5,jsx会将语法首位空格删去中间如果有空格都会缩写成一个空格,另外单写的porps会默认为true,关于 true false undefined null 都不会被渲染,注意一下判断
<div>{list.length && 1}</div> list.length 为 0 页面显示会是0
<div>{list.length>0 && 1}</div> 应该要使用表达式
10,关于控制React,以及不可变数据触发Dom更新
1,react 可以通过 shouldComponentUpdate 控制对比nextProps nextState更新 return true 更新,return false 不更新,
react 可以通过props和state改变去渲染dom,如果props和state没更新,dom将不会更新。
2,可以通过React.PureComponent 创建组件,自动进行props和state浅比较更新,注意的是在改变state和props的值时,不能直接修改引用的值,再次赋值给state。
使用Array.concat或者Object.assign 返回新对象进行赋值更新。
11,React.protals 将React dom挂载到对应的节点
1,react.protals('reactDom','节点dom对象'),使用场景模态框,可以将reactDom挂载到外层的dom节点上,当本组件的子节点被全部渲染之后才会,挂载渲染protals组件。
可以在componentDidMount 函数中 element.appendChild(this.el) ,组件就会在挂载时立即挂载渲染protals,在 protals组件上一级组件中定义点击事件,protals可以将事件冒泡到上一级组件触发
12,关于react dom key 的渲染更新
1,react的渲染是指,通过虚拟dom比较,要不要往真实页面中改变渲染dom。react 不加key的情况下,会从上层递归遍历到下层元素,先判断元素类型再判断元素属性及标签中的内容进行更新
2,react在加key的情况下,和上一次的dom进行对比,不同的key就根据新dom顺序新建,相同key的情况,递归先判断元素类型,再判断元素属性状态更新及标签中的内容,决定是否重新渲染,如果是不受控表单组件,无法获取对比表单中的值,导致更新错误。
13,React 静态类相关检查
1,引入 flow.js 或者 typescipt.js 进行类和变量检查
2,React 自带的严格模式标签包裹需要检查的组件进行检查
3,引入 React 自带的propType
可以配置类型也可以配置默认值
import propType from 'prop-type'
ReactComponent.propType = {
name:propType.string,
age:'18'
}
14,React组件补充
1,React组件受控组件,指的是组件受到外界值得影响,通常指收到state props值得更改而改变。不受控组件是指组件的值和用户操作时是一致的,
不受任何处理,获取最后值可以传递到其他地方进出包装处理及后续操作。
2,关于 WebComponents 组件是谷歌提出的一套自定义组件标准,目前大多数浏览器已支持
标签:React,指引,return,dom,react,state,文档,props,组件 From: https://www.cnblogs.com/gmh-web/p/16740648.html