React

Introduction to the React

React,由 FaceBook 普及,是一个用于构建用户界面的开源 JavaScript 库。通过 JSX 创建组件,处理 state 和 props,利用事件监听和指定的生命周期钩子动态更新数据。

React 混合了 HTML 和 JavaScript 的函数性创建了一个新的标签语言,JSX。

创建一个简单的 JSX 元素

简介:React 是由 Facebook 创建和维护的开源视图库。它是渲染当代 Web 应用程序用户界面(UI)的绝佳工具。

React 使用名为 JSX 的 JavaScript 语法扩展,允许你直接在 JavaScript 中编写 HTML。这有几个好处。它允许你在 HTML 中使用 JavaScript 的完整程序功能,并有助于保持代码的可读性。在大多数情况下,JSX 类似于已经学过的 HTML

例如,因为 JSX 是 JavaScript 的语法扩展,所以实际上可以直接在 JSX 中编写 JavaScript。要做到这一点,只需在花括号中包含你希望被视为 JavaScript 的代码:{“这被视为 JavaScript 代码”}

但是,由于浏览器不能解析 JSX,因此必须将 JSX 代码编译为 JavaScript。在这个过程中,转换器 Babel 是一个很受欢迎的工具。

1
const JSX = <h1>Hello JSX!</h1>

创建一个复杂的 JSX 元素

JSX 也可以表示更复杂的 HTML。

关于嵌套的 JSX,需要知道的一件重要的事情,那就是它必须返回单个元素。

父元素将包裹所有其他级别的嵌套元素。

例如,几个作为兄弟元素而编写的JSX元素没有父元素包裹将不会被转换

1
2
3
4
5
6
<!--有效的JSX-->
<div>
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>
</div>

在 JSX 中添加注释

使用{/* */}语法来包裹注释文本

1
2
3
4
5
6
7
const JSX = (
<div>
{/*就离谱*/}
<h1>This is a block of JSX</h1>
<p>Here's a subtitle</p>
</div>
);

渲染 HTML 元素为 DOM 树

渲染 API(ReactDOM)将此 JSX 直接渲染到 HTML DOM。

ReactDOM 提供了一个简单的方法来将 React 元素呈现给 DOM,如下所示:ReactDOM.render(componentToRender, targetNode),其中第一个参数是要渲染的 React 元素或组件,第二个参数是要将组件渲染到的 DOM 节点。

1
2
3
4
5
6
7
8
const JSX = (
<div>
<h1>Hello World</h1>
<p>Lets render this to the DOM</p>
</div>
);

ReactDOM.render(JSX, document.getElementById('challenge-node'))

在 JSX 中定义一个 HTML Class

到目前为止,HTML 和 JSX 似乎完全相同。

JSX 的一个关键区别是你不能再使用class这个单词来定义 HTML 的 class 名。这是因为class是 JavaScript 中的关键字。JSX 使用className代替。

事实上,JSX 中所有 HTML 属性和事件引用的命名约定都变成了驼峰式。例如,JSX 中的单击事件是 onClick,而不是 onclick。同样,onchange变成了onChange。虽然这是一个微妙的差异,但一定要记住。

1
2
3
4
5
const JSX = (
<div className='myDiv'>
<h1>Add a class to this div</h1>
</div>
);

了解自动闭合的 JSX 标记

JSX 不同于 HTML 的另一个重要方面是自闭合标签在 JSX 中,规则略有不同。任何 JSX 元素都可以使用自闭合标签编写,并且每个元素都必须关闭。例如,换行标签必须始终编写为<br />。另一方面<div>可以写成<div />或者<div></div>。不同之处在于,在第一个语法版本中,无法在<div />中包含任何内容。

创建一个无状态的函数组件

使用 JavaScript 函数创建React组件,以这种方式定义组件会创建无状态功能组件

无状态组件视为可以接收数据并对其进行渲染的组件,但是它不管理或跟踪对数据的更改.

要用函数创建组件,只需编写一个返回 JSX 或null的 JavaScript 函数。需要注意的一点是,React 要求你的函数名以大写字母开头。下面是一个无状态功能组件的示例,该组件在 JSX 中分配一个 HTML 的 class:

1
2
3
4
5
const DemoComponent = function() {
return (
<div className='customClass' />
);
};

创建一个 React 组件

定义 React 组件的另一种方法是使用 ES6 的class语法。在以下示例中,Kitten扩展了React.Component

1
2
3
4
5
6
7
8
9
10
11
class Kitten extends React.Component {
constructor(props) {
super(props);
}

render() {
return (
<h1>Hi</h1>
);
}
}

用组合的方式创建一个 React 组件

创建了三个组件:NavbarDashboardFooter。创建一个App父组件,将这三个组件分别渲染成为子组件,在render方法中,你可以这样编写:

1
2
3
4
5
6
7
return (
<App>
<Navbar />
<Dashboard />
<Footer />
</App>
)

当 React 遇到引用另一个组件的自定义 HTML 标签时(如本例所示,组件名称包含在< />中),它在标签的位置渲染该组件的标签。这可以说明App组件和NavbarDashboard以及Footer之间的父子关系。

渲染 class 组件为 Dom 树

如果不调用 ReactDOM API,你编写的任何 React 代码都不会渲染到 DOM。

ReactDOM.render(componentToRender, targetNode)。第一个参数是要渲染的 React 组件。第二个参数是要在其中渲染该组件的 DOM 节点

React 组件传递到ReactDOM.render()与 JSX 元素略有不同。对于 JSX 元素,你传入的是要渲染的元素的名称。但是,对于 React 组件,你需要使用与渲染嵌套组件相同的语法:

ReactDOM.render(<ComponentToRender />, targetNode)

写一个 React 组件

1
2
3
4
5
6
7
8
9
10
class MyComponent extends React.Component{
constructor(prop){
super(prop);
}
render(){
return <div><h1>My First React Component!</h1></div>
}
}

ReactDOM.render(<MyComponent />, document.getElementById('challenge-node'))

将 Props 传递给无状态函数组件

现在是时候看看 React 中的另一个常见特性 props 了。在 React 中,你可以将属性传递给子组件。假设你有一个App组件,该组件渲染了一个名为Welcome的子组件,它是一个无状态函数组件。可以通过以下方式给Welcome传递一个user属性:

1
2
3
<App>
<Welcome user='Mark' />
</App>

使用自定义 HTML 属性,React 支持将属性user传递给组件Welcome。由于Welcome是一个无状态函数组件,它可以像这样访问该值:

1
const Welcome = (props) => <h1>Hello, {props.user}!</h1>

调用props这个值是常见做法,当处理无状态函数组件时,基本上可以将其视为返回 JSX 的函数的参数。这样,就可以在函数体中访问该值。但对于类组件,访问方式会略有不同。

传递一个数组作为 Props

要将数组传递给 JSX 元素,必须将其视为 JavaScript 并用花括号括起来。

1
2
3
<ParentComponent>
<ChildComponent colors={["green", "blue", "red"]} />
</ParentComponent>

这样,子组件就可以访问数组属性colors。访问属性时可以使用join()等数组方法。

1
2
3
const ChildComponent = (props) => <p>{props.colors.join(', ')}</p>

<!--将会生成 <p>green, blue, red</p> -->

使用默认的 Props

React 还有一个设置默认 props 的选项。将默认 props 作为组件本身的属性分配给组件,React 会在必要时分配默认 prop。例如,如果你声明MyComponent.defaultProps = { location: 'San Francisco' },即定义一个 location 属性,并且其值在没有另行制定的情况下被设置为字符串San Francisco。如果 props 未定义,则 React 会分配默认 props,但如果你将null作为 prop 的值,它将保持null

覆盖默认的 Props

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const Items = (props) => {
return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>
}

Items.defaultProps = {
quantity: 0
}

class ShoppingCart extends React.Component {
constructor(props) {
super(props);
}
render() {
return <Items quantity={10}/>
{ /* above this line */ }
}
};

使用 PropTypes 来定义你期望的 Props

你可以在组件上设置propTypes,以要求数据的类型为array。当数据是任何其他类型时,都会抛出警告。当你提前知道 prop 的类型时,最好的做法是设置propTypes。可以为组件定义propTypes属性,方法与定义defaultProps相同。这样做将检查给定键的 prop 是否是给定类型。这里有一个示例,名为handleClick的 prop 应为function类型:

1
MyComponent.propTypes = { handleClick: PropTypes.func.isRequired }

PropTypes.func部分检查handleClick是否为函数。添加isRequired是为了告诉 ReacthandleClick是该组件的必需属性。如果未提供该 prop,你将看到警告信息。另请注意,func表示function。在 7 种 JavaScript 基本类型中,functionboolean(写为bool)是仅有的使用异常拼写的两种类型。除了基本类型,还有其他类型可用

PropTypes可以从 React 中单独引入,如下所示:

1
import React, { PropTypes } from 'react';

使用 this.props 访问 Props

倘若接收 prop 的子组件不是无状态函数组件,而是一个 ES6 类组件又当如何呢?ES6 类组件访问 props 的方法略有不同。

任何时候,只要引用类组件本身,就要使用this关键字。要访问类组件中的 props,需要在在访问它的代码前面添加this。例如,如果 ES6 类组件有一个名为data的 prop,可以在 JSX 中这样写:{this.props.data}

使用 Props 和无状态函数组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class CampSite extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Camper />
</div>
);
}
};

const Camper = (props)=>{
return <p>{props.name}</p>
}

Camper.defaultProps = {
name: 'CamperBot'
}

Camper.propTypes = {
name: PropTypes.string.isRequired
}