React基础-核心概念

一、props

1、什么是props?

定义:props是父子组件之间通信的纽带,它表示的是父组件传递过来的自定义属性和children。

props是一个对象,通过props可以访问到父组件传递过来的自定义属性和children。

props是只读的(不能修改它)

通过props,可以向子组件传递ReactNode(ReactElement、基本数据类型、数组、JSX对象)、普通对象、函数等。

2、React的两种组件

什么组件?组件就是一个段可以被复用代码块。组件化的意义:封装快速开发。

进一步理解组件:组件实际就是一个“函数”,它接收props作为入参,返回用于视图渲染的JSX元素。因为props是只读的,所以每一个React组件都是一个“纯函数”。(什么是纯函数?入参不能改,给相同入参时总是返回唯一的结果。)

提示:虽然props不能修改,但可以参与业务逻辑运算。

(一)函数式组件(无状态组件)

const Hello = (props) => (<div></div>)

特点:它只有props,没有state状态,也没有this、生命周期、ref、上下文等特性。所以它的性能较好。

提示:自 React v16.8 以后,我们可以通过 Hooks API 来模拟上述缺失的React特性。

(二)类组件(有状态组件)

class Hello extends React.Component { // this.props }

特点:它有props,也有state状态、this、生命周期、ref、上下文等特性。相对于函数式组件其性能较差。

提示:自 React v16.8 以后,类组件越来越少使用了。现在市场中主流是Hooks+函数式组件。

3、父子组件

什么是 props.children ?它代表是自定义组件内部所嵌套的ReactNode列表。

在自定义属性时,不要把属性名命名为 children,因为它有特殊含义。

在props.children向子组件传递children时,建议传递ReactNode列表,不要传递普通数据。如果要传递数据,建议使用自定义props。

4、父子组件通信:父传子使用自定义属性,子传父通过自定义事件。(从Vue的角度来理解父子组件)

父组件给的props如果是“普通数据”,用于渲染、用于逻辑操作。

父组件给的props如果是“函数”,在子组件中可调用并向父组件返回数据。

父组件给的props如果“JSX对象”,在子组件中直接参与渲染。

5、props是“组件化(组合)”的语法基础。

二、state

1、描述

state 是React组件自身的数据,具有“响应式”的特性(当state变量被this.setState()修改时,视图会自动更新)。

这里的“响应式”和vue响应式是完全不同的,React中没有“数据支持、依赖收集”等工作。

1、定义state

在类组件中才有state(函数式组件中没有state),必须在constructor这个生命周期中定义state。

state必须“先定义、再使用”。state变量一般是基本数据类型、数组、普通对象。不能定义其它的数据类型。

2、使用state

在类组件中,使用this.state来访问所有的state变量。

3、state的特点

当使用this.setState()这个专属方法来修改state时,这会触发render()运行并返回新的“Fiber”,进一步执行“协调运行”(找到最小化的脏节点集合),最后一次“提交”更新DOM。

state是当前组件的“自有数据”,可以通过props传递给后代组件,但不能传递给父组件。这就是React中“单向数据流”(自上而下)。

4、如何优雅地修改state变量?

修改state变量必须使用this.setState()这个专属方法。不要直接修改state,因为直接修改state不会触发render()。

每次修改state时都要考虑“新值与旧值是否有”,如果有关使用this.setState(fn,callback)这种语法,如果无关使用this.setState({},callback)这种语法。

示例:this.setState({name:'GP8'}) this.setState(state=>({count:state.count+1}))

5、this.setState()异步性

在合成事件(on*开头的系列事件、生命周期钩子)中,this.setState()是异步的。

在微任务函数体中(Promise.then)中,this.setState()是同步的。

在非合成事件中(定时器、DOM事件)中,this.setState()是同步的。

this.setState() 为什么默认是异步?

因为开发者在同一个“合成事件”中有可能多次调用this.setState(),如果它同步的,这会导致多次render(),这显然是一种性能损耗。所以,React在设计this.setState()把它变成异步的,这样的好处是更好保证this.setState()的浅合并,以节省性能。

什么是合成事件?

on*事件处理器、生命周期钩子都是合成事件。合成事件是React官方专门封装一组API,这些合成事件是“可控的”,React就可以放心地把合成事件中的this.setState()变成异步的,目的是为了对多个this.setState()进行浅合并,以节省性能。

this.setState()在合成事件中是异步的。那我们如何知道这个异步任务完成了?

方案一:this.setState(fn|{}, callback) 在callback被调用时就说明这个异步工作完成了。

方案二:componentDidUpdate() 当这个生命周期被触发时,说明这个异步工作完成了。

建议:React官方建议,方案二更靠谱,方案一尽量少用。

测试this.setState()的同步性:在非合成事件中,它都是同步的。如果一定要给个解释,React无法操控“非合成事件”,所以没有办法把this.setState()变成异步的,所以也不存在性能优化。

场景一:在定时器中,this.setState()是同步的。

场景二:用dom、ref的方式绑定事件,在事件处理器中,this.setState()也是同步的。

场景三:在new Promise().then()中,this.setState()是同步的。(异议:后面再用真实ajax测试)

6、this.setState() 浅合并

理解:在同一个更新周期(合成事件)中,如果多次调用this.setState(),React会自动将它们合并,以节省性能。

三、事件

事件绑定原则:尽可能地使用合成事件来绑定事件。

合成事件:https://zh-hans.reactjs.org/docs/events.html

1、如何绑定事件?

语法一:使用ES5的方式来绑定事件 onClick={this.handle.bind(this)}

语法二:使用ES6的方式来绑定事件 onClick={()=>this.handle()}

建议:使用“语法二”来绑定事件

2、如何拿到事件对象?

ES5方式绑定事件,事件处理器的最后一个参数永远都事件对象。

ES6方式绑定事件,需要手动传递事件对象。

3、事件处理器如何自定义传递参数?

ES5方式事件传参,onClick={this.handle.bind(this, 'arg', ...)}

ES6方式事件传参,onClick={ev=>this.handle('arg', ev)}

4、如何阻止冒泡、默认事件?

用事件对象的api来实现(二阶段的知识)

ev.stopPropagation()

ev.preventDefault()

5、如何监听键盘事件?

用事件对象的api来实现(二阶段的知识) ev.keyCode

四、条件渲染

条件渲染:元素的显示与隐藏,这里巧用的都是JSX语法。

1、单一元素的条件渲染

语法:{ bol && <jsx> }

2、两个元素的条件渲染

语法: { bol ? <jsx1> : <jsx2> }

3、多个元素的条件渲染

语法:建议封装“自定义的渲染函数” function renderThing() { return <jsx> }

4、动态class

语法:className={'类名的拼接'}

5、动态style

语法:style={ css样式的键值对 }

五、列表渲染

列表渲染:React官方建议使用map()进行渲染

语法基础:JSX支持对数组的渲染。

为什么官方建议使用map()方法来实现列表渲染?

语法:const newList = list.map(fn),

特点:map()方法的特点,对源数据进行fn处理,返回一个新的jsx数组。

六、表单绑定

表单绑定:除了文件上传以外,都要使用受控表单。

1、两类表单

受控表单,表单/类表单的value或checked由state控制着。

非受控表单,表单/类表单的value或checked与state完全无关。

原则:除了文件上传以外,所有表单都必须是受控表单。

对于普通文本表单、select表单,用value属性来受控,用onChange取值。

对于radio/checkbox表单,用checked属性来受控,用onChange取值。

对于自定义的“类表单”,我们建议用自定义属性value来受控,用自定义onChange取值。

2、表单的单向绑定

意思是在React中表单的取值操作必须手动完成。

最佳实践:当页面中表单特别多时,我们只封装一个change handler来取所有表单的值。也就是对change handler方法的复用。复用的方式有很多,可以自定义dataset自定义事件传参来实现。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容