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自定义事件传参来实现。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容