React中文文档之Components and Props

Components and Props - 组件和属性
组件允许你分隔UI为独立的、可重用的零件,每个零件是隔离的。
概念上,组件就像js的函数。它们接收任意的输入(被称为 'props'),并返回React元素,用以描述应该在屏幕上显示的内容。


Functional and Class Components - 函数式组件和类组件
定义一个组件的最简单方式是写一个js函数:
		function Welcome(props) {
			return <h1>Hello, {props.name}</h1>;
		}

这个函数是一个有效的React组件,因为它接收单个的 'props' 对象参数,并返回一个 'React元素'(同组件的定义相同)。我们称这样的组件为 '函数式',因为,它们字面上是js函数。
你也可以使用一个ES6类来定义一个组件:
		class Welcome extends React.Component {
			render() {
				return <h1>Hello, {this.props.name}</h1>;
			}
		}

从React的角度来看,这2个组件是等同的。
类组件有一些额外的功能,我们将在下章节讨论。接下来,我们将使用函数式组件,因为它们的简洁性。


Rendering a Component - 渲染一个组件
之前,我们仅碰到过React元素,代表DOM标签:
		const element = <div />;
然而,元素也可以代表用户定义的组件:
		const element = <Welcome name="dong" />;

当React看到一个代表用户定义组件的元素时,它将JSX属性传递给这个组件,JSX属性作为单个对象,我们称为 'props'。
例如,下面的代码在页面上渲染 'Hello, Sara':
		function Welcome(props) {
			return <h1>Hello, {props.name}</h1>
		}
		const element = <Welcome name="Sara" />;
		ReactDOM.render(
			element,
			document.getElementById('root');
		);

让我们简要阐述上面这个例子中都发生了什么:
1.我们使用 '<Welcome name="Sara" />',调用 'ReactDOM.render()'。
2.React调用 'Welcome' 组件,传递 '{name: 'Sara'}' 作为props。
3.我们的 'Welcome' 组件返回一个 '<h1>Hello, Sara</h1>' 元素作为结果。
4.React DOM高效地更新DOM为 '<h1>Hello, Sara</h1>'
警告:
组件名总是以 '大写字母' 开始。
例如,'<div />' 代表一个 DOM 标签,而 '<Welcome />'代表一个组件,并包含'Welcome'到作用域内。

Composing Components - 组件构成
组件可在输出中,包含其他组件。这让我们对于任何级别的细节,都可以使用相同的组件抽象。在React应用中,按钮、表单、对话框、屏幕,所有的这些都可以被表示为组件。
例如,,我们创建一个 'App' 组件,多次渲染 'Welcome' 组件:
		function Welcome(props) {
			return <h1>Hello, {props.name}</h1>;	
		}
		function App() {
			return (
				<div>
					<Welcome name="dong" />
					<Welcome name="xue" />
					<Welcome name="min" />
				</div>
			);
		}
		ReactDOM.render(
			<App />,
			document.getElementById('root')
		);

明显的,新的React应用在顶级,包含单个 'App' 组件。然而,如果你将React和一个已经存在的应用融合,你可能想要以一个小的、底层的组件开始,就像 'Button' 组件,并以你的方式,逐步涉及到视图层的顶部。
警告:
组件必需返回单个的 'root element - 根元素'。这也是为什么我们在所有的 <Welcome /> 组件外层,添加一个 <div> 的原因。

Extracting Components - 提取组件
别害怕将组件分隔成更小的组件。
例如,思考这个 'Comment' 组件:
		function Comment(props) {
			return (
			    <div className="Comment">
			      	<div className="UserInfo">
			        	<img className="Avatar"
			          		src={props.author.avatarUrl}
			          		alt={props.author.name}
			        	/>
			        	<div className="UserInfo-name">
			          		{props.author.name}
				        </div>
			      	</div>
			      	<div className="Comment-text">
			        	{props.text}
			      	</div>
			      	<div className="Comment-date">
			        	{formatDate(props.date)}
			      	</div>
			    </div>
			);
		}

它接收 'author'(对象),'text'(字符串),'date'(日期) 作为props,描述了一个在社交媒体网站上的评论。
因为所有的嵌套,这个组件不容易被改变,并且重用它的各部分也很困难。
首先,我们将提取 'Avatar' 组件:
		function Avatar(props) {
			return (
	        	<img className="Avatar"
	          		src={props.author.avatarUrl}
	          		alt={props.author.name}
	        	/>
			);
		}

'Avatar' 组件不需要知道它被渲染在一个 'Comment' 组件内部。这就是为什么我们给了它一个更通用的名字作为它的props:'user' 而不是 'author'。(该组件可用于很多场合,而非只是评论、文章)
我们建议从组件的角度来考虑,而不是从它正在使用的上下文,来命名 'props'。
现在我们可以把 'Comment' 组件简化一点点:
		function Comment(props) {
			return (
			    <div className="Comment">
			      	<div className="UserInfo">
			      		<Avatar user={props.author} />
			        	<div className="UserInfo-name">
			          		{props.author.name}
				        </div>
			      	</div>
			      	<div className="Comment-text">
			        	{props.text}
			      	</div>
			      	<div className="Comment-date">
			        	{formatDate(props.date)}
			      	</div>
			    </div>
			);
		}

下一步,我们将提取 'UserInfo' 组件,在用户名的下方显示头像:
		function UserInfo(props) {
			return (
				<div className="UserInfo">
					<Avatar user={props.user} />
				</div>
	        	<div className="UserInfo-name">
	          		{props.author.name}
		        </div>
			);
		}

这让我们更进一步简化 'Comment' 组件:
		function Comment(props) {
			return (
			    <div className="Comment">
			    	<UserInfo user={props.author} />
			      	<div className="Comment-text">
			        	{props.text}
			      	</div>
			      	<div className="Comment-date">
			        	{formatDate(props.date)}
			      	</div>
			    </div>
			);
		}

提取组件最初可能看着是繁重的工作,但是将有一个可重用的组件库的回报,在一些更大的应用中。提取组件的一个好的经验是:如果你的UI中的一部分使用了好多次(按钮、面板、头像),或者组件本身有点复杂(App、FeedStory、Comment),就应该提取组件。

Props are Read-Only - 属性是只读的
不管你使用函数式还是类,声明一个组件,绝不能修改它自己的props。思考 'sum' 函数:
		function sum(a, b) {
			return a + b;
		}

这类函数被称作 'pure'(纯函数),因为它们不尝试修改它们的输入,并且相同的输入总是返回相同的结果。
与此相反,下面的函数式不纯的,因为它修改了自己的输入:
		function withdraw(account, mount) {
			account.total -= amount;	
		}

React是相当灵活的,但是它有一个严格的规定:
所有React组件必需表现的像纯函数一样,尊重它们的props(props会传递给组件,所以不能修改props)
当然,UI应用是动态的,可以随着时间改变。在下个章节,我们将介绍一个新的概念,'state-状态'。state状态允许组件随着时间改变它们的输出,来响应用户操作、网络响应以及其他任何别的,而不会去破环上面这条规则!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值