简介

React.js 是一个帮助我们构建页面 UI 的库。

React.js 不是一个框架,它只是一个库。它只提供 UI(view) 层面的解决方案。在实际的项目中,它并不能解决我们所有的问题,需要结合其它的库,例如 Redux、React-router 等来协助提供完整的解决方法。

React.js 基本环境搭建

工具地址:https://github.com/facebookincubator/create-react-app

它可以一键生成所需要的工程目录,并帮我们做好各种配置和依赖,也帮我们隐藏了这些配置的细节。

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

使用 JSX 描述 UI 信息

「在 JavaScript 中写标签」的语法叫 「JSX」。所谓的 JSX 其实就是 JavaScript 对象。

1
2
3
4
// 要写 React.js 组件,那么就必须要引入这两个东西
import React, { Component } from 'react';
// ReactDOM 可以帮助我们把 React 组件渲染到页面上去,没有其它的作用了
import ReactDOM from 'react-dom';

关于 ‘react-dom’:
为什么不直接从 JSX 直接渲染构造 DOM 结构,而是要经过中间这么一层呢?

  1. 渲染对象
    当我们拿到一个表示 UI 的结构和信息的对象以后,不一定会把元素渲染到浏览器的普通页面上,我们有可能把这个结构渲染到 canvas 上,或者是手机 App 上。所以这也是为什么会要把 react-dom 单独抽离出来的原因,可以想象有一个叫 react-canvas 可以帮我们把 UI 渲染到 canvas 上,或者是有一个叫 react-app 可以帮我们把它转换成原生的 App(实际上这玩意叫 ReactNative);
  2. 更新效率
    当数据变化,需要更新组件的时候,就可以用比较快的算法操作这个 JavaScript 对象,而不用直接操作页面上的 DOM,这样可以尽量少的减少浏览器重排,极大地优化性能;

总结:

  1. JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并不是 HTML;
  2. JSX 在编译的时候会变成相应的 JavaScript 对象描述;
  3. react-dom 负责把这个用来描述 UI 信息的 JavaScript 对象变成 DOM 元素,并渲染到页面上;

组件的 render 方法

render 方法只能返回一个 JSX 元素,不能并列返回多个元素;

组件的组合、嵌套和组件树

自定义的组件都必须用大写字母开头,普通的 HTML 标签都用小写字母开头。

事件监听

监听

React.js 帮我们封装好了一系列的 on* 的属性,且不需要考虑不同浏览器兼容性的问题,React.js 都帮我们封装好这些细节了。

React.js 封装了不同类型的事件,参考官网文档:SyntheticEvent - React

没有经过特殊处理的话,这些 on* 的事件监听只能用在普通的 HTML 的标签上,而不能用在组件标签上。

event 对象

事件监听函数会被自动传入一个 event 对象,该对象是 React.js 对浏览器原生 event 对象封装出来的,符合 W3C标准 的。

事件中的this

React.js 是直接通过函数调用而不是通过对象方法的方式调用的,所以要手动 bind 绑定 this 以获取到实例。

组件的 state 和 setState

setState 方法由父类 Component 所提供,当调用这个函数的时候,React.js 会更新组件的状态 state,并且重新调用 render 方法,然后再把 render 方法所渲染的最新内容显示到页面上。

setState 可以接受一个对象或者函数作为参数。

React.js 内部会把 JS 事件循环中的消息队列的同一个消息中的 setState 都进行合并以后再重新渲染组件,所以不需要担心多次进行 setState 会带来性能问题。

配置组件的 props

在使用一个组件的时候,可以吧参数放在标签的属性当中,所有的属性都会作为 props 对象的键值对,组件内部就可以通过 this.props 来访问到这些配置参数了。

还可以配置默认的 props,也即是 defaultProps

props 一旦传进来就不能改变,否则会报错;但是可以通过父组件主动重新渲染的方式来传入新的 props

state vs props

两者职责明确:state 是让组件控制自己的状态,props 是让外部对组件自己进行配置。

没有 state 的组件叫「无状态组件」(stateless component),设置了 state 的叫做「有状态组件」(stateful component)。

因为状态会带来管理的复杂性,应尽量多地写无状态组件,尽量少写有状态的组件,以降低代码维护的难度,也在一定程度上增强组件的可复用性。

React.js 非常鼓励无状态组件,在 0.14 版本引入了函数式组件,也即一种定义不能使用 state 的组件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 原来写法,可以使用 state
class HelloWorld extends Component {
constructor () { super() }
sayHi () { console.log('Hello Wolrd'); }
render () { return (<div onClick={this.sayHi.bind(this)}>SayHi</div>); }
}
// 无状态函数组件,不能使用 state
// 函数式组件编写方式:
const HelloWorld = (props)=>{
const sayHi = (evt)=>{ console.log('Hello Wolrd'); };
return (<div onClick={sayHi}>SayHi</div>);
}

以前一个组件是通过继承 Component 来构建,一个子类就是一个组件。
而函数式组件是一个函数就是一个组件。
不同的是,无状态函数式组件智能接受 props 而无法像跟类组件一样可以在 constructor 里面初始化 state,可以理解函数式组件就是一种只能接受 props 和提供 render 方法的类组件。

注意:是「无状态函数组件」,而不是无状态组件,两个是不一样的概念。

SFC

无状态函数组件,又称 ‘Stateless Function Component’,简称 ‘SFC’。

SFC 是获取不到组件实例的,也就是那个 this;而且也没有、也不能使用组件的生命周期函数;

渲染列表数据

一般来说,在 React.js 处理列表就是用 map 来处理、渲染的。对于用表达式套数组罗列到页面上的元素,都要为每个元素加上 key 属性,该 key 必须是每个元素唯一的标识。

特殊的 props

在 React.js 中书写元素或组件属性的时候,有个别属性需要注意一下:

  • className
    由于 jsx 语法,组件或者元素都是一个 js 的对象,class 为关键字不能复用,就把样式属性定为 className
  • style
    写 style 的时候,必须是对象,且外层再包一对花括号;原来 css 属性中带 - 的元素都必须要去掉并换成驼峰命名;

实战分析

实现功能之前先理解、分析需求、划分组件;并且撞我划分组件的基本原则————可复用性、可维护性;