一:什么是组件
用官方文档的话来说,组件是允许你将UI拆分为独立可复用的代码片段,并对每个片段进行独立构思。也就是说,组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
例如上面图片中的代码,组件中拥有自己的状态,属性,也可能拥有方法等。
二:React的组件
在react中,拥有两种编写组件的方式
1. 类组件(Class 组件)
在class组件中,我们需要继承React.Component 来声明它是一个组件。
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
2. 函数组件
定义组件最简单的方式就是编写 JavaScript 函数:该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。
(1) function Welcome(props) { return <h1>Hello, {props.name}</h1>; } (2) const Welcome = (props.name) => { return <h1>hello,{props.name}</h1> }
关于类组件
在class中,除了继承React.Component 之外,还有updater ,props,setState等。
那么,在React的底层是如何定义类组件呢?
react源码的
react/src/ReactBaseClasses.js
function Component(props, context, updater) { this.props = props; //绑定props this.context = context; //绑定context this.refs = emptyObject; //绑定ref this.updater = updater || ReactNoopUpdateQueue; //上面所属的updater 对象 } /* 绑定setState 方法 */ Component.prototype.setState = function(partialState, callback) { this.updater.enqueueSetState(this, partialState, callback, 'setState'); } /* 绑定forceupdate 方法 */ Component.prototype.forceUpdate = function(callback) { this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); }
通过上述代码可以看出class 的底层处理逻辑。class组件执行构造函数过程中会在实例上绑定props跟context,并且还会默认初始化refs,同时会给它的 原型上绑定setState以及forceUpdate两个方法。
说到这里突然有个问题与大家探讨
还记得经常面试官问的问题吗,为什么在constructor的super中没有传递props,在这个组件里就再获取不到props。
答案就是上面的源码:
从源码中可以看出,绑定props是在父级的component的构造函数中,在子组件的super()方法等于执行了react底层中的Component函数,而此时的props却没有做为传递参数的第一个值传递过来给super()
所以我们在底层的Component方法中就会找不到props参数。所以接下来在在constructor的代码中打印props就会为undefined。
关于函数组件
React Hooks 出来后对函数组件的功能做了加强,可以在function组件中做类组件相同的事情,甚至现在在推荐代替类组件,并且官网文档也说了,
定义组件最简单的方式就是编写 JavaScript 函数
如上就是一个函数组件,我们可以利用React Hooks 来在函数组件中实现生命周期,监听,以及其它与class类组件类似的操作。
但是这里要注意的是:函数组件在react中,是直接调用执行函数的,而不是new 出来的。
两者的区别是什么呢?
对于类组件来说,只需要实例化一次,就可以保存组件的state状态,对于每一次更新只需要调用render方法以及对应的生命周期就可以了,但是在函数组件中,每一次更新都是一次新的执行,都会让里面的变量重新声明。
组件之间的通讯
React 一共介绍了五种流行通讯方式。
- props 和 callback 方式
- ref 方式。
- React-redux 或 React-mobx 状态管理方式。
- context 上下文方式。
- event bus 事件总线。
其中props 与 callback 的方式我们经常使用。
父组件 -> 通过自身 state 改变,重新渲染,传递 props -> 通知子组件
子组件 -> 通过调用父组件 props 方法 -> 通知父组件。
所以从这点上我们也可以看的出,React是一个单数据流。不能在子级中改变父级的东西,我们只能在子级通过调用父级的方法,让父级改自己的方式,然后重新传值渲染发生改变。
其它的各位伙伴可以自行尝试
组件之间的强化
如今的组件既然能拆分成一个个小单元,在良好编码的前提下,如果我们想松耦合加一个功能,做组件强化/拓展,我们如何去做呢?
1 、 类组件继承
达到的效果是:
此时会发现,子类狗(app)可以控制父类的render。并且还能增加自己的渲染内容。
同时也可以获取到父类的方法。
2. 函数组件自定义Hooks。
自定义Hooks,实际上就是把每个组件重复的逻辑单独抽离出来,然后封装成函数,只不过用use开头就好,不然用不了一些hooks。这里其实就类似于面向对象编程。但是一定要记得,名字要用use开头。
3. HOC高阶组件
自定义Hooks 的出现让我们在函数组件中也可以如鱼得水,它与类组件有着类似的操作。类组件是继承一个组件,合起来生成一个新组件。而我们的自定义函数组件则是接收一个方法,返回一个新的方法。
以上就是关于react组件的相关知识,大家如若有兴趣,可以下去再查一下五种通讯方式的具体实现。我在这里就不说了。一定要理清楚他们的具体实现以及优缺点,这可是面试长问问题。