乐趣区

关于react.js:React系列五创建React组件

快来退出咱们吧!

“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (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.propsthis.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'))

咱们简略解释一下下面这个例子:

  1. 咱们调用了 ReactDOM.render() 办法并向其中传入了 <Welcome name="xhs rookies" /> 元素。
  2. React 调用 Welcome 组件,并向其中传入了 {name: 'xhs rookies'} 作为 props 对象。
  3. Welcome 组件返回 <h1>xhs rookies</h1>
  4. 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 的一部分须要用屡次 (ButtonPanelAvatar),或者自身足够简单(AppFeedStoryComment),最好的做法是使其成为可复用组件。

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

退出移动版