React文档学习(2)
- 高级指南上半部分
深入JSX
在运行时选择类型
1 | import React from 'react'; |
对 JSX 类型使用点语法
1 | import React from 'react'; |
在xm项目中,写了很多
{条件?<div></div>:<div></div>}
这样的大量代码,其实可以写成点语法
JSX中的Children
Functions(函数) 作为 Children(子元素): props.children
的值可以是回调函数:
1 | function Repeat(props) { |
使用PropTypes进行类型检查
要求单独的 Child
- 使用
PropTypes.element
,你可以指定仅将单一子元素传递给组件,作为子节点
1 | import PropTypes from 'prop-types'; |
静态类型检查
- Flow 是一个针对 JavaScript 代码的静态类型检查器。它是在Facebook开发的,经常和React一起使用。 它可以让你使用特殊的类型语法来注释变量,函数和React组件,并尽早地发现错误。
- TypeScript 是一门由微软开发的编程语言。 它是 JavaScript 的一个类型超集,包含它自己的编译器。 作为一种类型化语言,Typescript 可以早在您的应用程序上线之前在构建时发现错误和错误。
Refs和DOM
添加Ref
- Refs用于在常规数据流外强制修改子元素。被修改的子元素可以是 React 组件实例,或者是一个 DOM 元素。
- 什么时候使用 refs 的场景:
- 处理focus、文本选择或者媒体播放
- 触发强制动画
- 集成第三方DOM库
ref
属性接受回调函数,并且当组件 装载(mounted) 或者 卸载(unmounted) 之后,回调函数会立即执行。React 组件在加载时将 DOM 元素拥有一个current属性,在卸载时则会传入
null
。在componentDidMount
或componentDidUpdate
这些生命周期回调之前执行ref
回调。创建Refs
1
2
3
4
5
6
7
8
9class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}可以在dom元素和类组件上天界Ref,不能在函数式组件上使用 ref 属性,可以在函数式组件内部使用 ref来引用一个 DOM 元素或者 类(class)组件
对父组件暴露DOM节点
从父组件访问子节点的 DOM 节点的途径
适用于类组件和函数式组件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
);
}
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el}
/>
);
}
}
不受控组件
- 受控组件,表单数据由React组件负责处理
- 不受控组件,表单数据由DOM元素本身处理
优化性能
- 可以通过重写生命周期函数
shouldComponentUpdate(nextProps,nextState)
来优化性能。 - 继承React.PureComponent就不需要手动写shouldComponentUpdate,但是React.PureComponent仅仅会进行浅比较,所以如果 props 或者 state 可能会导致浅比较失败的情况下就不能使用
React.PureComponent
了。
不可变数据
避免浅比较失败的方法是不要突变props或者state的值:
方法1:使用…或者Object.assign({}
1
2
3
4
5
6
7
8
9
10// 向数组添加内容
handleClick() {
this.setState(prevState => ({
words: [...prevState.words, 'marklar'],
}));
};
// 更改对象的值
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'blue'});
}方法2:使用 Immutable 数据结构
Immutable提供了通过结构共享实现(Structural Sharing)的、不可变的(Immutable)、原来集合在新集合创建之后仍然可用。
1
2
3
4
5
6
7
8
9
10
11
12
13// 原本方法,x会因为y的变动而改变
const x = { foo: 'bar' };
const y = x;
y.foo = 'baz';
x === y; // true
// 新的方法
const SomeRecord = Immutable.Record({ foo: null });
const x = new SomeRecord({ foo: 'bar' });
const y = x.set('foo', 'baz');
const z = x.set('foo', 'bar');
x === y; // false
x === z; // true
不使用ES6
- mixin简单通俗的讲就是把一个对象的方法和属性拷贝到另一个对象上,注意这个继承还是有区别的。js是一种只支持单继承的语言,毕竟一个对象只有一个原型,如果想实现多继承,那就简单暴力的把需要继承的父类的所有属性都拷贝到子类上,就是使用mixin。
- ES6不支持mixin,
createReactClass
可以允许使用mixins
。
一致性比较
无论什么时候,当根元素类型不同时,React 将会销毁原先的树并重写构建新的树。
keys 应该是稳定的、可预测的并且是唯一的。不稳定的 key (类似于
Math.random()
函数的结果)可能会产生非常多的组件实例并且 DOM 节点也会非必要性的重新创建。这将会造成极大的性能损失和组件内state的丢失。故在项目中采用拼接字符串的形式,而不是random来做
Context
- getChildContext()和childContextTypes将方法或者变量写成全局的,子树中的任务组件都可以通过定义contextTypes访问到
- 如果 contextTypes 在组件中定义,下列的生命周期方法将接受一个额外的参数——context 对象
- 如果
contextTypes
作为函数的属性被定义,无状态的函数式组件也可以引用context
Context更新而其组件不更新
- API上不建议Context进行更新。
- 网上查找的博文连接https://blog.csdn.net/liangklfang/article/details/72782920
1 | class ThemeProvider extends React.Component { |
1 | class ThemedText extends React.Component { |
1 | // 组件TodoList从props中获得todos属性,从而渲染出ThemedText组件 |
1 | const TODOS = ["Get coffee", "Eat cookies"] |
- 当点击按钮的时候,按钮本身颜色发生变化,但是TodoList这个组件没有变化。因为它继承了React.PureComponent,组件的props没有发生变化,shouldComponentUpdate返回了false,不管是TodoList还是他的子组件都不会重新渲染。因此,我们的TodoList里面的所有的组件颜色都不会发生变化
- 更加糟糕的是,我们也不能在TodoList中手动实现
shouldComponentUpdate(nextProps, nextState, nextContext)
,因为SCU根本就不会接收到context数据(只有当它的state或者props修改了才能接收到,getChildContext才会调用)。 - 因此,shouldComponentUpdate如果返回false,那么所有的子组件都不会接收到context的更新。如这里的TodoList组件返回了false,那么TodoList下所有的ThemedText从context中获取到的color都不会更新。