React教程第9部分:组件属性

在React教程的今天翻译中,我们将讨论组件属性。 这是该库中反映的最重要的概念之一。

图片

第1部分:课程概述,React,ReactDOM和JSX普及的原因
第2部分:功能组件
第3部分:组件文件,项目结构
第4部分:父级和子级组件
第5部分:TODO应用程序的开始工作,样式设计的基础
第6部分:关于本课程的一些功能,JSX和JavaScript
第7部分:内联样式
第8部分:继续研究TODO应用程序,熟悉组件的属性
第9部分:组件属性
第10部分:使用组件特性和样式的研讨会
第11部分:动态标记生成和映射数组方法
第12部分:研讨会,TODO应用程序的第三阶段工作
第13部分:基于类的组件
第14部分:关于基于类的组件,组件状态的研讨会
第15部分:组件健康研讨会
第16部分:TODO应用程序的第四阶段工作,事件处理
第17部分:TODO应用程序的第五阶段工作,修改组件的状态
第18部分:TODO应用程序的第六阶段工作
第19部分:组件生命周期方法
第20部分:条件渲染的第一课
第21部分:关于条件渲染的第二课​​和研讨会
第22部分:TODO应用程序的第七阶段工作,从外部资源下载数据
第23部分:关于使用表格的第一课
第24部分:第二形式课
第25部分:使用表单的研讨会
第26部分:应用程序体系结构,容器/组件模式
第27部分:课程项目

第19课。React中的组件属性


原创

使用create-react-app创建一个新项目,并从src文件夹中更改几个标准文件的代码。

这是index.js文件的代码:

 import React from "react" import ReactDOM from "react-dom" import "./index.css" import App from "./App" ReactDOM.render(<App />, document.getElementById("root")) 

以下是index.css文件中描述的样式:

 body { margin: 0; } .contacts { display: flex; flex-wrap: wrap; } .contact-card { flex-basis: 250px; margin: 20px; } .contact-card > img { width: 100%; height: auto; } .contact-card > h3 { text-align: center; } .contact-card > p { font-size: 12px; } 

这是在App.js文件中找到的代码:

 import React from "react" function App() {   return (       <div className="contacts">           <div className="contact-card">               <img align="center" src="http://placekitten.com/300/200"/>               <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>               <p>Phone: (212) 555-1234</p>               <p>Email: mr.whiskaz@catnap.meow</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/400/200"/>               <h3><font color="#3AC1EF">▍Fluffykins</font></h3>               <p>Phone: (212) 555-2345</p>               <p>Email: fluff@me.com</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/400/300"/>               <h3><font color="#3AC1EF">▍Destroyer</font></h3>               <p>Phone: (212) 555-3456</p>               <p>Email: ofworlds@yahoo.com</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/200/100"/>               <h3><font color="#3AC1EF">▍Felix</font></h3>               <p>Phone: (212) 555-4567</p>               <p>Email: thecat@hotmail.com</p>           </div>       </div>   ) } export default App 

这是该应用在浏览器中的外观。


浏览器中的应用程序页面

在分析了应用程序的代码和外观之后,我们可以得出结论,使用特殊的组件来显示带有动物信息的卡片会很好。 现在,这些元素是通过App组件形成的。 考虑到我们在之前的课程中所讨论的内容,您可以走得更远-考虑可以通过向其传递属性或属性来定制的通用组件。

在我们的应用程序中,有一些卡片,上面印有猫的图像,它们的名称以及所有者(或他们自己)的联系信息-电话和电子邮件地址。 为了创建以后将成为所有此类卡的基础的组件,您可以采用App组件返回的标记片段之一。 例如-这:

 <div className="contact-card">   <img align="center" src="http://placekitten.com/300/200"/>   <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>   <p>Phone: (212) 555-1234</p>   <p>Email: mr.whiskaz@catnap.meow</p> </div> 

App返回四个这样的块,每个块可用于创建独立的组件,但是这种方法不适合我们。 因此,我们将创建一个组件,该组件将成为应用程序显示的所有卡片的基础。 为此,请在src文件夹ContactCard.js创建一个新的组件文件,并在其中放入一个代码,该代码返回App组件返回的第一个<div>元素,其代码已在上面给出。 这是ContactCard组件的代码:

 import React from "react" function ContactCard() {   return (       <div className="contact-card">           <img align="center" src="http://placekitten.com/300/200"/>           <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>           <p>Phone: (212) 555-1234</p>           <p>Email: mr.whiskaz@catnap.meow</p>       </div>   ) } export default ContactCard 

显然,如果您创建此组件的多个实例,则所有这些实例都将包含相同的数据,因为此数据是硬编码在组件代码中的。 我们希望在创建此组件的不同实例时,可以自定义其显示的数据。 关键是可以向组件传递某些属性,然后他可以使用这些属性。

我们使用的功能组件是普通的JS函数,由于React库,在其中可以使用特殊的构造。 如您所知,尽管函数可以不带参数使用,但它们可以带参数。 我们的ContactCard组件的ContactCard现在已经存在)可以是一个简单的函数,无需接受任何内容,只需返回两个数字的和即可:

 function addNumbers() {   return 1 + 1 } 

它可以用来找出数字1和1的总和,但是,例如,要使用不接受任何输入的函数将数字1和2相加,我们将不得不编写一个新函数。 很明显,如果您需要添加不同的数字,这种方法会带来极大的不便,因此在这种情况下,创建一个通用函数来添加数字是明智的选择,该函数需要两个数字并返回它们的和:

 function addNumbers(a, b) {   return a + b } 

这样的函数返回什么取决于调用时传递给它的参数。 通过创建React组件,我们可以完全一样地进行。

我们将App.js组件ContactCard并返回其四个实例,而无需立即删除构成应用程序页面上卡片的代码:

 import React from "react" import ContactCard from "./ContactCard" function App() {   return (       <div className="contacts">           <ContactCard />           <ContactCard />           <ContactCard />           <ContactCard />           <div className="contact-card">               <img align="center" src="http://placekitten.com/300/200"/>               <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>               <p>Phone: (212) 555-1234</p>               <p>Email: mr.whiskaz@catnap.meow</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/400/200"/>               <h3><font color="#3AC1EF">▍Fluffykins</font></h3>               <p>Phone: (212) 555-2345</p>               <p>Email: fluff@me.com</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/400/300"/>               <h3><font color="#3AC1EF">▍Destroyer</font></h3>               <p>Phone: (212) 555-3456</p>               <p>Email: ofworlds@yahoo.com</p>           </div>                     <div className="contact-card">               <img align="center" src="http://placekitten.com/200/100"/>               <h3><font color="#3AC1EF">▍Felix</font></h3>               <p>Phone: (212) 555-4567</p>               <p>Email: thecat@hotmail.com</p>           </div>       </div>   ) } export default App 

现在,让我们研究用于实例化ContactCard组件的代码。 通过创建常规的HTML元素,我们可以自定义影响其行为和外观的属性。 这些属性的名称由标准硬编码。 对于组件,您可以使用完全相同的方法,唯一的区别是我们自己发明了属性的名称,并自行决定如何在组件代码中使用它们。

每个卡包含四个信息,每个卡可以更改这些信息。 这是猫和猫的名字以及电话和电子邮件地址的图像。 让猫的名字包含在name属性中, imgURL属性中的图像地址, imgURL属性中的phone以及email属性中的电子邮件地址。

我们将这些属性设置为ContactCard组件的实例,并且当我们从App已有的代码传输数据时,我们将删除其相应的片段。 结果, App组件的代码将如下所示:

 import React from "react" import ContactCard from "./ContactCard" function App() {   return (       <div className="contacts">           <ContactCard               name="Mr. Whiskerson"               imgUrl="http://placekitten.com/300/200"               phone="(212) 555-1234"               email="mr.whiskaz@catnap.meow"           />                     <ContactCard               name="Fluffykins"               imgUrl="http://placekitten.com/400/200"               phone="(212) 555-2345"               email="fluff@me.com"           />                     <ContactCard               name="Destroyer"               imgUrl="http://placekitten.com/400/300"               phone="(212) 555-3456"               email="ofworlds@yahoo.com"           />                     <ContactCard               name="Felix"               imgUrl="http://placekitten.com/200/100"               phone="(212) 555-4567"               email="thecat@hotmail.com"           />                 </div>   ) } export default App 

的确,仅将属性转移到组件不足以在组件中使用它们。 该页面将由上述App组件构成,将包含四张相同的卡,其数据已在ContactCard组件的代码中设置,但尚不知道如何处理传递给它的属性。


卡数据已硬编码在代码中;该组件无法使用传递给它的属性

因此,现在该谈谈ContactCard组件如何与实例化时传递给它的属性一起使用。

我们通过在声明ContactCard函数时指出它接受props参数来解决此问题。 在这种情况下,组件代码将如下所示:

 import React from "react" function ContactCard(props) {   return (       <div className="contact-card">           <img align="center" src="http://placekitten.com/300/200"/>           <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>           <p>Phone: (212) 555-1234</p>           <p>Email: mr.whiskaz@catnap.meow</p>       </div>   ) } export default ContactCard 

实际上,该参数可以随意命名,但是在React中,习惯上将其称为props ,而我们在这里谈论的属性通常简称为“ props”。

props参数是一个对象。 该对象的属性是实例化组件时传递给组件的属性。 也就是说,例如,在我们的props对象中props将有一个props.name属性, props.name包含在实例化时传递给组件的cat的名称。 此外,它将具有属性props.imgUrlprops.phoneprops.email 。 要验证这一点,请在ContactCard函数的开头添加console.log(props)命令。

 import React from "react" function ContactCard(props) {   console.log(props)   return (       <div className="contact-card">           <img align="center" src="http://placekitten.com/300/200"/>           <h3><font color="#3AC1EF">▍Mr. Whiskerson</font></h3>           <p>Phone: (212) 555-1234</p>           <p>Email: mr.whiskaz@catnap.meow</p>       </div>   ) } export default ContactCard 

这会将组件接收到的props对象带到控制台。


控制台道具对象

在这里,您可以看到ContactCard.js中四个对象的输出。 它们之所以太多,是因为我们创建了ContactCard组件的四个实例。

所有这些使我们有机会在组件代码中使用而不是硬编码的值,而是在创建其实例时传递给它的内容,这些props可以以props对象props的形式获得。

如果我们尝试props.imgUrl这样使用props.imgUrl属性,该props.imgUrl

 <img align="center" src=props.imgUrl/> 

乍一看,这种构造可能有效,但请记住,这里我们需要在JSX代码中使用JavaScript中的实体。 我们在上一课中讨论了如何完成此操作。 也就是说,在我们的例子中,对象的属性必须用大括号括起来:

 <img align="center" src={props.imgUrl}/> 

我们以相同的方式处理组件返回的其他元素,之后其代码将采用以下形式:

 import React from "react" function ContactCard(props) {   return (       <div className="contact-card">           <img align="center" src={props.imgUrl}/>           <h3><font color="#3AC1EF">▍{props.name}</font></h3>           <p>Phone: {props.phone}</p>           <p>Email: {props.email}</p>       </div>   ) } export default ContactCard 

请注意,在用于显示电话和电子邮件地址的字段中,我们在文本“ Phone:和“ Email:后面留有空格,因为这些文本在所有组件中均使用。 如果现在查看应用程序页面,您会注意到它包含四个不同的卡。


使用通用组件形成的页面

我们的组件仅接受四个属性。 如果某个组件需要传递例如50个属性该怎么办? 就像在App组件中那样,将每个这样的属性作为单独的一行传递可能会很不方便。 在这种情况下,可以使用另一种方式将属性传输到组件。 它包含以下事实:创建组件的实例时,它不会传递属性列表,而是传递具有属性的对象。 这是第一个组件示例的外观:

 import React from "react" import ContactCard from "./ContactCard" function App() {   return (       <div className="contacts">           <ContactCard               contact={{                 name: "Mr. Whiskerson",                 imgUrl: "http://placekitten.com/300/200",                 phone: "(212) 555-1234",                 email: "mr.whiskaz@catnap.meow"               }}           />                     <ContactCard               name="Fluffykins"               imgUrl="http://placekitten.com/400/200"               phone="(212) 555-2345"               email="fluff@me.com"           />                     <ContactCard               name="Destroyer"               imgUrl="http://placekitten.com/400/300"               phone="(212) 555-3456"               email="ofworlds@yahoo.com"           />                     <ContactCard               name="Felix"               imgUrl="http://placekitten.com/200/100"               phone="(212) 555-4567"               email="thecat@hotmail.com"           />                 </div>   ) } export default App 

这并不是说这种方法大大减少了用于描述组件实例的代码量。 事实是,尽管我们仅将一个组件传递给组件,但是传递给组件的属性仍然在代码中进行了硬编码。 在从某些外部源获取组件数据的情况下,可以感受到这种方法的优势。 例如,来自JSON文件。

在修改用于创建ContactCard组件的第一个实例的App组件的代码期间,该App的正确操作被中断。 这就是他的页面现在的样子。


应用程序故障

如何解决? 为了理解这一点,使用console.log(props)分析正在发生的事情将很有用。


道具对象分析

如您所见,第一个组件的props对象与第二个和下一个组件的相同对象不同。

ContactCard组件中ContactCard我们基于props对象具有nameimgUrl和其他属性的假设来使用。 在这里,第一个组件仅接收一个属性contact 。 这导致了一个事实,即props对象只有一个属性contact ,它是对象,并且组件代码不提供这种结构的工作。

将我们的组件转换为仅使用包含其他属性的contact对象的一个​​属性的模型非常简单。 为此,例如,要访问name属性, props.contact.name在组件代码中使用props.contact.name形式的构造props.contact.name 。 类似的设计使我们可以与我们需要的其他属性一起正常工作。

让我们回收组件代码,并考虑到包含其他属性的单个属性-对象contact的转移:

 import React from "react" function ContactCard(props) {   console.log(props)   return (       <div className="contact-card">           <img align="center" src={props.contact.imgUrl}/>           <h3><font color="#3AC1EF">▍{props.contact.name}</font></h3>           <p>Phone: {props.contact.phone}</p>           <p>Email: {props.contact.email}</p>       </div>   ) } export default ContactCard 

现在应该可以正常显示第一个组件,但是在项目的此阶段我们将看不到该组件,因为系统会通知我们许多错误,这些错误与以下事实有关:在App组件中创建的ContactCard组件的多个实例未接收到以下属性: contact对象。 执行代码时,此属性为undefined 。 结果,尝试引用undefined值的某个属性,这会导致错误。 我们将通过处理负责形成ContactCard组件的App组件的代码来解决此问题:

 import React from "react" import ContactCard from "./ContactCard" function App() {   return (       <div className="contacts">           <ContactCard               contact={{                 name: "Mr. Whiskerson",                 imgUrl: "http://placekitten.com/300/200",                 phone: "(212) 555-1234",                 email: "mr.whiskaz@catnap.meow"               }}           />                     <ContactCard               contact={{                 name: "Fluffykins",                 imgUrl: "http://placekitten.com/400/200",                 phone: "(212) 555-2345",                 email: "fluff@me.com"               }}           />                     <ContactCard               contact={{                 name: "Destroyer",                 imgUrl: "http://placekitten.com/400/300",                 phone: "(212) 555-3456",                 email: "ofworlds@yahoo.com"               }}           />                     <ContactCard               contact={{                 name: "Felix",                 imgUrl: "http://placekitten.com/200/100",                 phone: "(212) 555-4567",                 email: "thecat@hotmail.com"               }}           />                 </div>   ) } export default App 

现在,应用程序页面将与以前相同。

像往常一样,建议您尝试使用今天学到的概念,以便更好地理解它们。 例如,您可以使用代码,添加传递给组件的新属性,然后尝试在组件中使用它们。

总结


今天,我们介绍了可以传递给React组件以控制其行为和外观的属性的概念。 这些属性类似于HTML元素的属性,但是,程序员使用组件中的属性,可以独立地决定它们的含义以及组件中的确切含义。 下次,您将获得有关使用组件属性和样式的实践课程。

亲爱的读者们! 为了更好地理解React组件的属性,您如何尝试使用今天示例的代码?

Source: https://habr.com/ru/post/zh-CN436032/


All Articles