快来退出咱们吧!
“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (https://xhs-rookies.com/) 进行学习,及时获取最新文章。
“Code tailor”,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励!
前言
这节咱们将介绍 React
中组件的类别,以及如何创立和应用组件。
本文会向你介绍以下内容:
- 创立类组件
- 创立函数组件
- 渲染组件
- 合成组件
- 提取组件
- Props 是只读的
组件介绍
组件(Components
) 让你能够将用户界面分成独立的,可复用的小部件,并能够对每个部件进行独自的设计。
从定义上来说,组件就像 JavaScript
的函数。组件能够接管任意输出(称为”props
”),并返回 React
元素,用以形容屏幕显示内容。
Props
,即属性(Property
),在代码中写作props
,故可用props
指代properties
。
react
中有两种组件:类组件(class components
)、函数组件(function components
)
创立类组件
类组件的定义有如下要求:
- 类组件须要继承自
React.Component
- 类组件必须实现
render
函数
在 ES6
之前,能够通过 create-react-class
模块来定义类组件,然而目前官网倡议咱们应用ES6
的 class 类定义。
应用 class
定义一个组件:
class App extends Component {constructor() {super()
this.state = {}}
render() {return <h2>Hello App</h2>}
}
咱们来详细分析一下类组件有哪几个局部
constructor:
这是类组件的构造函数,是可选的,咱们通常在constructor
中初始化一些数据;this.state:
咱们在constructor
中给类组件退出state
属性,你能够了解为组件中有一个state
对象,其中蕴含着各种属性,用于保护组件外部的数据。同时你能够通过this.state.< 属性名 >
拜访该属性;render():
该办法是class
组件中惟一必须实现的办法,类组件通过render()
返回组件的显示内容;
对于 state
咱们能够通过 this.state
给类组件增加数据对象,咱们能够通过 this.state.< 属性名 >
去拜访咱们 setState
中的属性。
constructor(props) {super(props);
this.state = {name:"xhs-rookies"}
}
render(){return <h2>{this.state.name}</h2>
}
然而咱们想要批改上述例子中的 name
属性的时候,则必须通过 react
给咱们规定好的 setState()
办法,去给 state
增加或者批改其中的数值。
this.state.name = 'new xhs-rookies' // 谬误的形式,不容许采纳
this.setState({name: 'new xhs-rookies'}) // 正确的形式
简略点来说,在
react
中页面是通过数据进行渲染,应用setState()
更新的数据,react
会帮咱们执行render()
去更新页面,从而将页面中用到state
中的数据全副更新。
对于 render
当 render
被调用时,它会查看 this.props
和 this.state
的变动并返回很多类型,很多时候咱们抉择让该办法返回 React
元素,而后交由 React
去渲染展现:
React 元素:
- 通常通过
JSX
创立。 - 例如,
<div/>
会被 React 渲染为 DOM 节点,<MyComponent/>
会被 React 渲染为自定义组件; - 无论是
<div/>
还是<MyComponent/>
均为 React 元素。
具体对于
render()
办法的内容请见 React.Component – Render)
创立函数组件
函数组件是应用 function
来进行定义的函数,只是这个函数会返回和类组件中 render
函数返回一样的内容。
跟类组件相比,函数组件有本人的特点:
- 没有生命周期,也会被更新并挂载,然而没有生命周期函数;
- 没有
this
(组件实例); - 没有外部状态(
state
);
咱们来定义一个函数组件:
export default function App() {return <div>xhs rookies</div>}
渲染组件
在前几篇中, 咱们只遇到代表 DOM 标签的 React 元素:
const element = <div />
然而,元素也能够代表用户定义的组件:
const element = <Welcome name="xhs rookies" />
当 React
遇到一个代表用户定义组件的元素时,它将 JSX
属性以一个独自对象的模式传递给相应的组件。咱们将其称为“props
”对象。
比方, 以下代码在页面上渲染“xhs rookies”
:
function Welcome(props) {return <h1>Hello, {props.name}</h1>
}
const element = <Welcome name="xhs rookies" />
ReactDOM.render(element, document.getElementById('root'))
咱们简略解释一下下面这个例子:
- 咱们调用了
ReactDOM.render()
办法并向其中传入了<Welcome name="xhs rookies" />
元素。 React
调用Welcome
组件,并向其中传入了{name: 'xhs rookies'}
作为props
对象。Welcome
组件返回<h1>xhs rookies</h1>
。React DOM
迅速更新DOM
,使其显示为<h1>xhs rookies</h1>
。
留神: 组件名称总是以大写字母开始。
举例来说,
<div/>
代表一个 DOM 标签,而<Welcome/>
则代表一个组件,并且须要在作用域中有一个Welcome
组件。你能够深刻 JSX 浏览更多对于这点背地的起因。
合成组件
组件能够在它们的输入中援用其它组件。这使得咱们能够应用同样的组件来形象到任意层级。一个按钮,一个表单,一个对话框,一个屏幕:在 React
利用中,所有这些都通常形容为组件。
例如,咱们能够创立一个 App
组件,并在其外部屡次渲染 Welcome
:
function Welcome(props) {return <h1>Hello, {props.name}</h1>
}
function App() {
return (
<div>
<Welcome name="rookie-Sara" />
<Welcome name="rookie-Cahal" />
<Welcome name="rookie-Edite" />
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
通常,新的 React apps
都有一个独自的顶层 App
组件。然而,如果你在已有的利用中整合 React
,你能够须要由下至上地, 从相似于 Button
这样的小组件开始, 逐步整合到视图层的顶层。
提取组件
不要胆怯把一个组件分为多个更小的组件。
举个例子,思考下名 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.user.avatarUrl} alt={props.user.name} />
}
Avatar
组件不必关怀它在 Comment
中是如何渲染的。这是为什么咱们它的 prop
一个更通用的属性名: 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
组件,用于将 Avatar
显示在用户名旁边:
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">{props.user.name}</div>
</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>
)
}
提取组件可能看起来是一个繁琐的工作,然而在大型的 Apps
中能够回报给咱们的是大量的可复用组件。一个好的教训准则是如果你 UI
的一部分须要用屡次 (Button
,Panel
,Avatar
),或者自身足够简单(App
,FeedStory
,Comment
),最好的做法是使其成为可复用组件。
Props 是只读的
无论你用函数或类的办法来申明组件, 它都无奈批改其本身 props. 思考下列 sum
(求和)函数:
function sum(a, b) {return a + b}
这种函数称为“纯函数”,因为它们不会试图扭转它们的输出,并且对于同样的输出, 始终能够失去雷同的后果。
反之,以下是非纯函数,因为它扭转了本身的输出值:
function withdraw(account, amount) {account.total -= amount}
尽管 React
很灵便,然而它有一条严格的规定:
留神: 所有
React
组件都必须是纯函数,并禁止批改其本身props
。
当然,利用 UI
总是动静的,并且随时有能够扭转。
如果咱们想要动静扭转 UI
,那么就会波及到咱们下面说到的 state
(状态)。咱们通过动静的扭转state
来渲染整个页面,咱们前面会提及,详情见 深刻了解 setState