「React」
React(有时叫 React.js 或 ReactJS )是一个用于构建用户界面的 JavaScript 库。
在安装了 Node.js 后,使用如下命令快速搭建 React 开发环境:
npx create-react-app my-app
清空 src 文件夹并在里面编写代码,之后通过 npm start 命令启动你的 React 应用。
「JSX」
1.JSX 是 JS 的语法扩展,常配合 React 使用,例如:
const name = 'Bob'
const element =
Hello, {name}
大括号里面可以是任何 JS 表达式;
2.JSX 也是一个表达式,因此可以赋值给变量、作为函数参数或返回值;
3.JSX 中可以为属性值指定字符串字面量或 JS 表达式:
const element =
const element = ;
需要使用 camelCase 来定义属性名称,例如 class 变成 className;
4.可以安全地在 JSX 中插入用户输入的内容,会默认转义,有效防止 XSS 攻击;
5.Babel 会把 JSX 转译成 React.createElement() 函数调用,创建出一个称为 React 元素的对象。
「元素」
1.元素是构成 React 应用的最小砖块,是创建开销极小的普通对象,React DOM 负责更新 DOM 来与元素保持一致;
2.要将一个元素渲染到根 DOM 节点中,需使用 render():
const element =
Hello, world
;ReactDOM.render(element, document.getElementById('root'));
3.元素是不可变对象,一旦创建就无法更改其子元素或者属性,它代表了某个特定时刻的 UI;
4.React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。
「组件与 props」
1.组件类似函数,它接受 props,返回用于描述页面展示内容的 React 元素;
2.定义组件的第一种方式是函数组件,例如:
function Welcome(props) {
return
Hello, {props.name}
;}
3.第二种方式是 class,例如:
class Welcome extends React.Component {
render() {
return
Hello, {this.props.name}
;}
}
每次组件更新时 render 方法都会被调用;
4.元素也可以是用户自定义组件,首字母需大写,例如:
const element = ;
其中属性都会转换为一个 props 对象传递给组件,组件内使用 this.props 获取到;
5.对于可复用的组件,应将组件拆分成更小的组件提取出来;
6.所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
「state」
1.state 是私有的且完全受控于当前组件;
2.定义 state 可在 class 组件里加入 state 对象,例如:
state = {
prizes: [],
gameOver: false
}
3.更新 state 则使用 setState() 而不是直接修改 state,例如:
this.setState({
prizes: [],
gameOver: true
})
4.每当 state 改变时会重新调用 render();
5.state 的更新可能是异步的,React 可能会把多个 setState 调用合并成一个;
6.如果把一个以组件构成的树想象成一个 props 的数据瀑布的话,那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源,但是它只能向下流动;
7.state 代表来随时间会产生变化的数据,应当仅在实现交互时使用。
「生命周期方法」
每个组件在运行过程的特定阶段会执行不同的生命周期方法。组件第一次被渲染到 DOM 中时称为挂载(mount),从 DOM 中被删除时称为卸载(unmount)。常用的生命周期方法如图所示:
「事件处理」
1.React 事件命名采用 camelCase 写法;
2.使用 JSX 语法时要传入一个函数作为事件处理函数,例如:
3.使用 class 定义组件时通常将事件处理函数声明为 class 中的方法,但这样需绑定 this。可以使用如下写法:
class LoggingButton extends React.Component {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。 // 注意: 这是 *实验性* 语法。 handleClick = () => {
console.log('this is:', this);
}
render() {
return (
Click me
);
}
}
4.若需要为事件处理函数传递额外的参数,有两种写法:
this.deleteRow(id, e)}>Delete Row
Delete Row
「条件渲染」
使用 if 或条件运算符来实现条件渲染。通过花括号包裹代码可以在 JSX 中嵌入任何表达式:
return (
Hello!
{str.length > 0 &&
You have {str.length} unread messages.
}
);
如果让 render 方法直接返回 null 能隐藏组件而不进行任何渲染。
「列表渲染」
return (
{numbers.map((number) =>
value={number} />
)}
);
其中 key 是必须的,最好是这个元素在列表中拥有的独一无二值,不建议使用索引 index。
「受控组件」
在 React 中可变状态通常保存在组件的 state 中,并且只能通过 setState() 来更新。当一个表单输入元素用 state 作为唯一数据源,且表单操作被组件控制时,称其为受控组件。例如:
其中 handleChange:
handleChange(event) {
this.setState({value: event.target.value});
}
, 和 之类的标签都可以实现受控组件。
「props.children」
有时候组件无法提前知晓其子组件的具体内容时,可使用 props.children:
function FancyBorder(props) {
return (
{props.children}
);
}
这样在 标签中的所有内容都会作为 children 这个 prop 传递给 FancyBorder 组件,类似 Vue 里面的插槽。
「Fragment」
Fragments 用于将子列表分组,而不会向 DOM 添加额外节点。例:
render() {
return (
HelloWorld);
}
key 是唯一可以传递给 Fragment 的属性。
「高阶组件 HOC」
高阶组件 HOC 是一种基于 React 的组合特性而形成的设计模式,具体而言高阶组件是参数为组件,返回值为新组件的函数。
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。
使用 HOC 一般有下述几个约定:
1.HOC 不应该修改传入组件而应该使用组合的方式;
2.不要在 render() 中使用 HOC;
3.新组件将没有原始组件的任何静态方法,因此务必复制静态方法。
「PropTypes」
可以使用 React 内置的类型检查功能对组件的 props 进行类型检查,当传入的 prop 类型不正确时,控制台将显示警告。
这是通过 propTypes 实现的,仅在开发模式下进行检查。首先引入 PropTypes:
import PropTypes from 'prop-types’;
常用的检查有:
MyComponent.propTypes = {
// 你可以将属性声明为 JS 原生类型,默认情况下 // 这些属性都是可选的。 optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括数字、字符串、元素或数组) // (或 Fragment) 也包含这些类型。 optionalNode: PropTypes.node,
// 一个 React 元素。 optionalElement: PropTypes.element,
// 一个 React 元素类型(即,MyComponent)。 optionalElementType: PropTypes.elementType,
// 你也可以声明 prop 为类的实例,这里使用 // JS 的 instanceof 操作符。 optionalMessage: PropTypes.instanceOf(Message),
// 你可以让你的 prop 只能是特定的值,指定它为 // 枚举类型。 optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 一个对象可以是几种类型中的任意一个类型 optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 可以指定一个数组由某一类型的元素组成 optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 可以指定一个对象由某一类型的值组成 optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 可以指定一个对象由特定的类型值组成 optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保 // 这个 prop 没有被提供时,会打印警告信息。 requiredFunc: PropTypes.func.isRequired,
// 任意类型的数据 requiredAny: PropTypes.any.isRequired,
// 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。 // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。 customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
}
};
「其他」
1.组件可以接受任意 props,并通过 import 组合其他组件,因此完全不需要使用到继承;
2.根据单一功能原则来判断组件范围,一个组件原则上只负责一个功能,否则考虑拆分;
3.开发过程中通常先开发一个不包含交互的 UI,然后添加交互;
4.React 通过一种比传统的双向绑定略繁琐的方法来实现反向数据传递:父组件传入一个能改变 state 的回调函数给子组件;
5.React 中有一个命名规范,通常将代表事件监听的 prop 命名为 on[Event],将处理事件监听的方法命名为 handle[Event] ;
6.有两种改变数据的方式,一种是直接修改变量,另一种是使用新的一份数据替换旧数据,后者称为不可变性,可以轻松确定何时对组件进行重新渲染。