安装

React在codepen上提供了一个Hello,World项目事例,只需打开网站,即可尝试React。
另外还提供了一个html文件的Hello,World项目,项目中引用CDN的react.js、react-dom.js以及用于编译babel的babel.min.js,运行比较缓慢,只适合学习语法使用。

创建单页面应用

创建React应用的最好方法是单页面应用,这里是最好方法,也是可以创建多页面应用的。可以通过官方方法去创建你的应用:

1
2
3
4
npm install -g create-react-app
create-create-app hello-world
cd hello-world
npm start

这里不涉及任何后端逻辑和数据库,可以使用任何你想用的后端。create-react-app中使用了Webpack,Babel和ESLint,但是你可以自己去配置他们。

将React加入一个现有的应用

使用npm install --save react react-dom安装React。
将其导入你的代码中,如:

1
2
3
4
5
6
7
import React from 'react';
import ReactDOM from 'react-dom'; ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
)

这段代码应该被包含在一个拥有id为root的HTML元素,所以你的HTML文件需要<div id="root"></div>
当你使用上面方法使用React的时候,需要使用预设为es2015和react的Babel进行转化代码。使用React在生产环境的时候,设置NODE_ENV为”production”。

使用ES6和JSX

建议是用Babel将你的ES6和JSX代码转换为JavaScript代码,Babel可以有很多不同的配置,但是确保里面包含babel-preset-reactbabel-preset-es2015

使用CDN

如果不想使用npm,可以使用CDN

1
2
<script src="https://unpkg.com/react@15/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>

@后面数字可以指定版本

1
2
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>

JSX

在JSX中,可以在任意地方插入JavaScript代码,只需要将JavaScript放在大括号中即可。下面的代码都是合法的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function (user) {
return user.firstName + ' ' + user.lastName;
} const user = {
firstName: 'Harper',
lastName: 'Perez'
}; const element = (
<h1>
Hello, {formatName(user)}!
</h1>
); ReactDOM.render(
element,
document.getElementById('root')
);

将JSX代码放在小括号中,像HTML代码一样换行,可以方便阅读。

JSX也是表达式

JSX最后也被编译成JavaScript代码,这就以为着JSX可以赋值给一个JavaScript变量,可以作为方法的参数,可以被方法返回。

JSX添加HTML属性

可以用字符串设置属性,也可以通过使用{}将JavaScript表达式赋值给属性。

闭合JSX

如果JSX是空的可以使用/>来闭合标签,如果包含其他标签,也可以使用</***>闭合。
虽然JSX很接近HTML,但是还是有些不同,比如属性使用小驼峰法命名,class使用className,for使用forHtml等。

JSX防止注入攻击

默认情况下,React DOM在渲染JSX之前会对其进行编码。

JSX描述对象

Babel会将JSX转化为React.createElement()形式,比如下面这样:

1
2
3
4
5
const element = (
<h1 className="greeting">
Hello, world!
</h1>
)

转化为

1
2
3
4
5
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

React.createElement会对你的代码进行一些检查,但是本质上就是将其转化成一个对象:

1
2
3
4
5
6
7
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
}

组件

将你的页面分成一个个组件,每个组件都是独立的、可以重复使用的。组件就像JavaScript中的方法,可以接受一些输入参数,返回React元素

Funtional 和 Class 组件

定义组件最简单的方式是使用JavaScript方法:

1
2
3
4
5
6
7
8
9
10
11
12
function Welcome (props) {
return <h1>Hello, {props.name}</h1>
}
这个方法就是个有效的React组件,因为它接受props作为参数,并且返回了一个React元素。 另外也可以使用ES6中的类(class)来定义组件:
```javascript
class Welcome extends React.Component {
render () {
return <h1>Hello, {this.props.name}</h1>
}
}

上面两种定义组件的方法是等价的。
但是Class组件能够添加一些额外的功能,我们将在下面讨论。在不需要这些额外的方法,可以使用Functional组件。

渲染组件

渲染如下:

1
2
3
4
5
6
7
8
9
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
} const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);

过程:

  1. 调用ReactDOM.render()方法,参数为自定义组件。
  2. React调用组件Welcome,传递{name="Sara"}作为参数。
  3. Welcome组件返回<h1>Hello, Sara</h1>
  4. React将<h1>Hello, Sara</h1>更新到页面。
组件组合

组件可以任意组合。
通常情况,React应用中在最顶端是一个App组件。组件必须有一个根元素,也就是所有元素都得包裹起来。

提取组件

不要担心组件被拆分的太小。下面是一个对组件进行拆分的例子。
Comment组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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>
);
}

大专栏  React Docs(1)re>

在Comment组件中,使用了author (object)text (string)date (date)来描述这个对象。这样的组件因为组合的原因是很难复用的。

第一步,提取出一个Avatar组件:

1
2
3
4
5
6
7
8
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}

这里的Avatar组件我们系统他更通用,所以说用了user而不是author
根据组件去命名参数,而不是根据使用上下文。

下一步是提取UserInfo组件,这里使用了上面提取的Avatar组件:

1
2
3
4
5
6
7
8
9
10
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}

这样,我们的Comment组件就成了下面的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
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>
);
}
Props是只读的

无论是Funcional还是Class组件,都是不能够修改props的。

1
2
3
4
5
6
7
8
function sum(a, b) {
return a + b;
}
// 下面这个不是纯函数,因为他改变了输入的值
function withdraw(account, amount) {
account.total -= amount;
}

通过官方这个例子,可以明白纯函数有两点,一是相同的输入就会有相同的输出,第二点是不会更改输入的参数。

所有的React组件对于props参数必须像纯函数一样,也就是不会试图去修改props,并且对于相同的props会有相同的输出。
当然,React也提供了随时间动态变化组件的方法,state允许根据用户行为、网络反馈等改变React组件的输出形式,这并不违背React纯函数原则。

state 和 生命周期

请看下面一段代码:

1
2
3
4
5
6
7
8
9
10
const Clock = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
<Clock />,
document.getElementById('root')
);

这段代码只能够显示一个Hello,world!与一个生成页面的时间。如果想要时间不停的更新,就需要使用setInterval()不停的去执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 这样
function tick() {
const Clock = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
}
setInterval(tick, 1000); // 或者这样
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
} function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000); // 但是下面这种就是不可行的,原因在于Clock组件定义被转化成了一个对象,在之后没有发生过变化。
const Clock = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
setInterval(
function(){
ReactDOM.render(
<Clock />,
document.getElementById('root')
)}, 1000)

这样的代码的问题在于时间的变化应该是Clock组件的行为,而不应该定义在全局。
state可以帮助我们解决这个问题,state与props类似,但是更私有且被组件所控制,而不是传递过来的。

将Functional组件转换为Class组件

Functional组件是无状态组件,不能使用state,所以首先需要将Functional转化为Class组件:

  1. 创建一个和Functional组件名相同的ES6 class继承React.Component
  2. 添加空的方法render()
  3. 将Functional组件中的函数主体移动render()方法中
  4. render()中的props替换成this.props
  5. 删除原来的Functional组件声明
    Class组件不仅可以使用state还可以使用生命周期函数。
    拿上面的Clock组件作为事例,经过上面的转换,现在的Clock组件应该是这个样子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Clock extends React.Component {
    render() {
    return (
    <div>
    <h1>Hello, world!</h1>
    <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
    </div>
    );
    }
    }
为Class组件添加本地state

还是上面的Clock组件:

  1. render()中的this.props替换成this.state
  2. 添加class构造函数(constructor)初始化this.state (Class组件总是应该将props传递给父类)
  3. 移除date从组件调用的props中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class Clock extends React.Component {
    // 这里是步骤2
    constructor(props) {
    // 将props传递给父类
    super(props);
    this.state = {date: new Date()};
    } render() {
    return (
    <div>
    <h1>Hello, world!</h1>
    <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
    </div>
    );
    }
    } ReactDOM.render(
    <Clock />,
    document.getElementById('root')
    );

这样只是初始化了state,后面会设置定时器。

React Docs(1)的更多相关文章

  1. react入门(3)

    在第一篇文章里我们介绍了jsx.组件.css写法  点击查看react入门(1) 第二篇文章里我们介绍了事件.this.props.children.props....other.map循环  点击查 ...

  2. react基础(1)

    在 react入门系列 里面,介绍了一些react的基础知识,在react基础部分,会结合手脚架工具进行更多的总结. 关于webpack我在这里就不讲解了,有需要的小伙伴可以自己去百度一下学习资料,我 ...

  3. react基础(2)

    react基础(1):介绍了如何创建项目,总结了JSX.组件.样式.事件.state.props.refs.map循环,另外还讲了mock数据和ajax 还是用 react基础1 里创建的项目继续写案 ...

  4. How React Works (一)首次渲染

    How React Works (一)首次渲染 一.前言 本文将会通过一个简单的例子,结合React源码(v 16.4.2)来说明 React 是如何工作的,并且帮助读者理解 ReactElement ...

  5. react初始(1)

    前言:react框架的出现是因为Facebook在建设Instagram交流平台的时候要处理大量的数据流,但是行业流行的MVC框架并不能适合Facebook公司的要求,他们就组织了自己的人力来开发re ...

  6. React系列(一):React入门

    React简介 1.由来 React是有Facebook开发出来用于构建前端界面的JS组件库,由于其背后的强大背景,使得这款库在技术开发上完全没有问题. 2.React的优势 解决大规模项目开发中数据 ...

  7. React教程(一) React介绍与搭建

    React的介绍: React来自于Facebook公司的开源项目 React 可以开发单页面应用 spa(单页面应用) react 组件化模块化 开发模式 React通过对DOM的模拟(虚拟dom) ...

  8. React项目(二):生命游戏

    引子 这是16年最后的一个练手项目,一贯的感觉就是,做项目容易,写说明文档难.更何况是一个唤起抑郁感觉的项目,码下的每个字,心就如加了一个千斤的砝码. 2016年,有些事我都已忘记,但我现在还记得.2 ...

  9. react入门(1)

    这篇文章也不能算教程咯,就算是自己学习整理的笔记把. 关于react一些相关的简介.优势之类的,随便百度一下一大堆,我就不多说了,可以去官网(http://reactjs.cn/)看一下. 这片主要讲 ...

随机推荐

  1. IMX6开发板虚拟机加载Ubuntu12.04.2镜像

    基于迅为IMX6开发板安装好虚拟机之后,用户就可以加载 Ubuntu12.04.2 镜像.用户可以在网盘中下载“编译好的镜像”,该镜像已经安装好了编译 Android4.4.2 所需要的大部分软件.用 ...

  2. Ioc和依赖注入

     转自https://www.cnblogs.com/zhangzonghua/p/8540701.html 1.IOC 是什么 IOC- Inversion of Control , 即“控制反转” ...

  3. Rnotebook中用python画图

    如果notebook需要转化为pdf, 能想到办法是保存图片文件,嵌入mardown语法中. 但是如果在html中显示, 可以考虑下面思虑, 比较取巧. ``` {python, engine.pat ...

  4. android物理动画、Kotlin客户端、架构组件、菜单效果、应用选择器等源码

    Android精选源码 Android一个有趣的Android动画交互设计 android可伸缩日历效果源码 关于界面,全新的卡片风格,支持夜晚模式 Android 用 Kotlin 实现的基于物理的 ...

  5. imx6q-plus-Android6.0下uboot添加网卡驱动

    1.文件:iTOP-iMX6_android6.0.1/bootable/bootloader/uboot-imx/include/configs/mx6sabre_common.h修改如下:#def ...

  6. WMS备货单保存后自动新增选项不勾选

  7. crm项目-stark组件分析

    ###############    stark组件     ################ """ 这个stark组件是非常神奇的 1,独立的一个组件 2,没有mod ...

  8. MOOC(13) - 连接数据库

    散装代码 # -*- coding: utf-8 -*- # @Time : 2020/2/18 9:00 # @File : connect_db_21.py # @Author: Hero Liu ...

  9. LeetCode No.70,71,72

    No.70 ClimbStairs 爬楼梯 题目 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. ...

  10. UFT场景恢复

    场景恢复: 在脚本运行中可能会出现一些非预期事件.错误.程序崩溃等情况,阻止脚本继续执行下去,在此情况下脚本可能暂停执行, 直到某些界面被操作之后才会继续执行下去,为了处理这一类事件因此存在场景恢复. ...