在react中,我们可以这样认为一切皆组件。我们的项目就是基于组件。class 是类组件,function 则为函数式组件。本章我们就一起来仔仔细细的玩懂React的组件。资料部分搜集来源网络,如有侵权请联系我进行删除!
目录
用官方文档的话来说,组件是允许你将UI拆分为独立可复用的代码片段,并对每个片段进行独立构思。也就是说,组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
例如上面图片中的代码,组件中拥有自己的状态,属性,也可能拥有方法等。
在react中,拥有两种编写组件的方式
在class组件中,我们需要继承React.Component 来声明它是一个组件。
- class Welcome extends React.Component {
- render() {
- return <h1>Hello, {this.props.name}h1>;
- }
- }
定义组件最简单的方式就是编写 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 的方式我们经常使用。
父组件 -> 通过自身 state 改变,重新渲染,传递 props -> 通知子组件
子组件 -> 通过调用父组件 props 方法 -> 通知父组件。
所以从这点上我们也可以看的出,React是一个单数据流。不能在子级中改变父级的东西,我们只能在子级通过调用父级的方法,让父级改自己的方式,然后重新传值渲染发生改变。
其它的各位伙伴可以自行尝试
如今的组件既然能拆分成一个个小单元,在良好编码的前提下,如果我们想松耦合加一个功能,做组件强化/拓展,我们如何去做呢?
1 、 类组件继承
达到的效果是:
此时会发现,子类狗(app)可以控制父类的render。并且还能增加自己的渲染内容。
同时也可以获取到父类的方法。
2. 函数组件自定义Hooks。
自定义Hooks,实际上就是把每个组件重复的逻辑单独抽离出来,然后封装成函数,只不过用use开头就好,不然用不了一些hooks。这里其实就类似于面向对象编程。但是一定要记得,名字要用use开头。
3. HOC高阶组件
自定义Hooks 的出现让我们在函数组件中也可以如鱼得水,它与类组件有着类似的操作。类组件是继承一个组件,合起来生成一个新组件。而我们的自定义函数组件则是接收一个方法,返回一个新的方法。
以上就是关于react组件的相关知识,大家如若有兴趣,可以下去再查一下五种通讯方式的具体实现。我在这里就不说了。一定要理清楚他们的具体实现以及优缺点,这可是面试长问问题。