前面一章,我们学习了如何利用函数创建一个 React 组件。但是由于没有学习如何传入参数,所以灵活性比较差。
我们接下来要思考的一个问题,如果,我们想要往函数组件中,传入一些参数应该怎么办呢?
1function Profile(props) {2return (3<div>4<h1>{props.name}</h1>5</div>6)7}
在 React 中,我们通常将参数称为 Props。他通过在元素标签中,添加属性的方式向组件内容传入参数。例如,我们封装了一个 Profile
组件,但是,这个组件需要展示不同用户的信息,因此,我们把用户的信息作为参数传入到组件中。
那么,在使用 Profile 组件时,就会有如下的写法,此时,我们将 avatar
、name
、description
作为参数传入到组件中。
1<Profile2avatar="https://i.imgur.com/1bX5QH6.jpg"3name="Lin Lanying"4description="Lin Lanying (1918-2003), a native of Putian, Fujian, was a Chinese physicist and academician of the Chinese Academy of Sciences..."5/>
所有的参数,都会聚合到一个 props
对象中,因此在组件内部,我们可以通过 props
来获取到传入的参数。例如,我们可以在组件中,通过 props.avatar
来获取到 avatar
参数,通过 props.name
来获取到 name
参数。并且,我们也可以通过 props.description
来获取到 description
参数。
10export default function Profile(props) {20const avatar = props.avatar30const name = props.name40const description = props.description5060return (70<div className='flex items-center gap-4'>80<img90className='w-40 rounded-xl'10src={avatar}11alt={name}12/>13<div>14<p className='!mt-0'>15<strong>name:</strong> {name}16</p>17<p className='!mb-0'>18{description}19</p>20</div>21</div>22)23}
如果要结合 TypeScript 来使用,我们通常需要为 props
添加类型声明。例如,在上一个组件中,我们需要为 Profile 组件添加如下类型声明
10interface ProfileProps {20avatar: string,30name: string,40description: string,50}6070export default function Profile(props: ProfileProps) {80const avatar = props.avatar90const name = props.name10const description = props.description1112return (13<div className='flex items-center gap-4'>14<img15className='w-40 rounded-xl'16src={avatar}17alt={name}18/>19<div>20<p className='!mt-0'>21<strong>name:</strong> {name}22</p>23<p className='!mb-0'>24{description}25</p>26</div>27</div>28)29}
Props 的类型声明,严格符合基础的 TypeScript
语法。如果有的参数不是必传的,我们可以在类型声明中,添加 ?
符号来表示这个参数是可选的。
1interface ProfileProps {2avatar: string,3name: string,4description?: string,5}
由于 Props 是一个正常的 JavaScript
对象,因此,我们也可以通过解构的方式,来获取到 Props 中的参数。例如,我们可以在组件中,通过 ES6 的解构语法来获取到 avatar
、name
、description
参数。
如下所示
1function Profile(props: ProfileProps) {2const { avatar, name, description } = props34return (5...6)7}
当然,更激进一点的做法是在函数参数中,直接解构获取。不过这样写有可能会降低代码的可读性,大家在使用时应该谨慎选择。
1function Profile({ avatar, name, description }: ProfileProps) {2return (3...4)5}
如果我们有一个字面量对象,此时,对象属性的 key
值与 props 对象的 key
值相同,那么,我们也可以通过展开运算符的方式,将对象的属性展开到 props 对象中。
10function App() {20const userinfo = {30avatar: 'https://i.imgur.com/szV5sdG.jpg',40name: 'Maria Skłodowska-Curie',50description: 'Maria Salomea Skłodowska-Curie[a] (ur. 7 listopada 1867 w Warszawie, zm. 4 lipca 1934 w Passy) – polsko-francuska uczona w dziedzinach fizyki doświadczalnej i chemii fizycznej...',60}7080return (90<Profile {...userinfo} />10)11}
这等价于
1<Profile2avatar="https://i.imgur.com/szV5sdG.jpg"3name="Maria Skłodowska-Curie"4description="Maria Salomea Skłodowska-Curie[a] (ur. 7 listopada 1867 w Warszawie, zm. 4 lipca 1934 w Passy) – polsko-francuska uczona w dziedzinach fizyki doświadczalnej i chemii fizycznej..."5/>
10interface ProfileProps {20avatar: string,30name: string,40description: string,50}6070export default function Profile(props: ProfileProps) {80const { avatar, name, description } = props9010return (11<div className='flex items-center gap-4'>12<img13className='w-40 rounded-xl'14src={avatar}15alt={name}16/>17<div>18<p className='!mt-0'>19<strong>name:</strong> {name}20</p>21<p className='!mb-0'>22{description}23</p>24</div>25</div>26)27}
有的时候,一个对象字段特别多,但是其中大部分字段都是与 props 对象的 key
相同,但是其中有个别字段是与 props 对象的 key
不同,那么,我们可以通过如下的方式来进行处理
10function App() {20const userinfo = {30avatar: 'https://i.imgur.com/szV5sdG.jpg',40name: 'Maria Skłodowska-Curie',50desc: 'Maria Salomea Skłodowska-Curie[a] (ur. 7 listopada 1867 w Warszawie, zm. 4 lipca 1934 w Passy) – polsko-francuska uczona w dziedzinach fizyki doświadczalnej i chemii fizycznej...',60}7080// 单独将不同的字段提取出来90const { desc, ...other } = userinfo1011return (12<Profile {...other} description={desc} />13)14}
如果在项目开发中,我们希望有一个组件可以方便的帮助我们定向到另外一个页面,例如我们从这个课程,跳转到另外一个课程中,那么,我们就可以借助上面所学到的知识,来自定义一个 Link 组件。
完整的代码和演示如下所示
10import Link from './link'2030export default function App() {40const links = {50href: '/r19plus',60title: 'React 19 . 架构尊享版',70desc: '加油学习,我在 React 19 的架构尊享版中等你哦 (ง•_•)ง',80}9010return (11<Link {...links} />12)13}14
ok,学习了这些基础知识之后,我们接下来,再来基于 img
标签封装一个头像组件,来巩固一下学习。