-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React 之元素与组件的区别 #317
Labels
Comments
写的很清晰 - 关于元素与组件如何区分和使用 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
从问题出发
我被问过这样一个问题:
想要实现一个
useTitle
方法,具体使用示例如下:但在编写
useTitle
代码的时候却出了问题:这段代码直接报错,连渲染都渲染不出来,如果是你,该如何修改这段代码呢?
元素与组件
其实这就是一个很典型的元素与组件如何区分和使用的问题。
元素
我们先看 React 官方文档中对 React 元素的介绍:
Babel 会把 JSX 转译成一个名为
React.createElement()
函数调用。以下两种示例代码完全等效:React.createElement()
会预先执行一些检查,以帮助你编写无错代码,但实际上它创建了一个这样的对象:这些对象被称为 “React 元素”。它们描述了你希望在屏幕上看到的内容。
你看,React 元素其实就是指我们日常编写的 JSX 代码,它会被 Babel 转义为一个函数调用,最终得到的结果是一个描述 DOM 结构的对象,它的数据结构本质是一个 JS 对象。
在 JSX 中,我们是可以嵌入表达式的,就比如:
所以如果我们要使用一个 React 元素,那我们应该使用嵌入表达式这种方式:
组件
那组件呢?组件有两种,函数组件和 class 组件:
那如何使用组件呢?
对于组件,我们要使用类似于 HTML 标签的方式进行调用,Babel 会将其转译为一个函数调用
所以你看,组件的数据结构本质是一个函数或者类,当你使用元素标签的方式进行调用时,函数或者类会被执行,最终返回一个 React 元素。
问题如何解决
尽管这些内容都来自于 React 官方文档,但如果你能清晰的了解到 React 元素和组件的差别,你已经可以解决开头的问题了。至少有两种方式可以解决,一种是返回 React 元素,一种是返回 React 组件
第一种我们返回 React 元素:
第二种我们返回 React 组件:
自定义内容
有的时候我们需要给组件传入一个自定义内容。
举个例子,我们实现了一个 Modal 组件,有确定按钮,有取消按钮,但 Modal 展示的内容为了更加灵活,我们提供了一个 props 属性,用户可以自定义一个组件传入其中,用户提供什么,Modal 就展示什么,Modal 相当于一个容器,那么,我们该怎么实现这个功能呢?
第一种实现方式
以下是第一种实现方式:
根据前面的知识,我们可以知道,
content
属性这里传入的其实是一个 React 元素,所以 Modal 组件的内部是用{}
进行渲染。第二种实现方式
但第一种方式,并不总能解决需求。有的时候,我们可能会用到组件内部的值。
就比如一个倒计时组件
Timer
,依然提供了一个属性content
,用于自定义时间的展示样式,时间由Timer
组件内部处理,展示样式则完全由用户自定义,在这种时候,我们就可以选择传入一个组件:在这个示例中,我们可以看到
content
属性传入的是一个 React 组件 CustomContent,而 CustomContent 组件会被传入 time 属性,我们正是基于这个约定进行的 CustomContent 组件的开发。而 Timer 组件内部,因为传入的是组件,所以使用的是
<Content time={time}/>
进行的渲染。第三种实现方式
在面对第二种实现方式的需求时,除了上面这种实现方式,还有一种称为
render props
的技巧,比第二种方式更常见一些,我们依然以 Timer 组件为例:鉴于我们传入的是一个函数,我们把
content
属性名改为了renderContent
,其实叫什么都可以。renderContent
传入了一个函数,该函数接收time
作为参数,返回一个 React 元素,而在Timer
内部,我们直接执行了 renderContent 函数,并传入内部处理好的 time 参数,由此实现了用户使用组件内部值自定义渲染内容。多说一句,除了放到属性里,我们也可以放到 children 里,是一样的:
我们可以视情况选择合适的传入方法。
React 系列
讲解 React 源码、React API 背后的实现机制,React 最佳实践、React 的发展与历史等,预计 50 篇左右,欢迎关注
如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: