继续上一次基础篇, 分享一些关于React的进阶技术

React 进阶部分

  • ** context **
  • ** setState vs forceUpdate **
  • ** Mixins **
  • ** HOC **

Components 相关

context

在 React 官方文档上有对 context 的说明:

Context is an advanced experimental feature. The API is likely to change in future releases

** context 如何工作? **

首先要在提供 context 的组件中定义 childContextTypesgetChildContext

  • childContextTypes: 静态属性, 声明传递下去的 context 的对象结构, 与 propTypes 类似, 但该属性是必须的
  • getChildContext: 定义在 prototype 上的方法, 返回将要传递下去的 context 对象,每次状态改变或该组件接收到新的 props 的时候该方法将被调用, 其实该方法是在 render()中执行的, 在组件的以下生命周期中能够访问 context
componentWillReceiveProps(nextProps,nextContext){...}
shouldComponentUpdate(nextProps,nextState,nextContext){...}
componentWillUpdate(nextProps,nextState,nextContext){...}
componentDidUpdate(previousProps,previousContext){...}

** 使用 context 的缺点 **

  1. React 中的 context 可能在将来发生变化, 这样依赖它的代码过于脆弱
  2. React 的 context 是单个子树范围的全局变量, 这样无疑提高了代码的耦合, 在该子树之外也很难重用
  3. 如果提供 context 的组件的 context 发生了变化, 使用 context 组件的任何一个父组件使用了 shouldComponentUpdate 返回了 false, 则使用者将不会发生更新

引入高阶组件能稍微缓解这些缺点

setState 接受 Function VS Object

为什么要传递函数到 setState ?

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

React可以将多个 setState() 调用批处理为单个更新以实现性能。

forceUpdate() VS setState()

** setState **

官方关于 setState 的描述

setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses.

官方关于 forceUpdate 的描述

By default, when your component's state or props change, your component will re-render. If your render() method depends on some other data, you can tell React that the component needs re-rendering by calling forceUpdate(). Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().

** 区别 **

forceUpdate() 会跳过 shouldComponentUpdate(), 不会修改当前的 state, setState() 与之不同

代码复用

Mixins && HOC

Mixins

现已不推荐

React Mixins [ _ 以下内容参考本文 _ ]

var LogMixin = {
componentWillMount: function () {
console.log('报告老板, 开始加载!');
},
componentDidMount: function () {
console.log('报告老板, 装载完毕!');
}
}; var AComponent = React.createClass({
mixins: [LogMixin],
render: function () {
return <h1>AComponent</h1>
}
}); var BComponent = React.createClass({
mixins: [LogMixin],
render: function () {
return <h1>BComponent</h1>
}
});

mixin 里的 this 指向组件

组件调用Mixins方法

var Mixin = {
log:function(){
console.log('Mixin log');
}
}; var Component = React.createClass({
mixins: [Mixin],
componentWillMount: function () {
this.log();
},
render: function () {
return <h1>Component</h1>
}
});

生命周期方法 [__ Mixins里的方法并不会覆盖组件的生命周期方法,会在先于组件生命周期方法执行。 __]

var Mixin = {
componentWillMount: function () {
console.log('Mixin Will Mount');
}
}; var Component = React.createClass({
mixins: [Mixin],
componentWillMount: function () {
console.log('Component Will Mount');
},
render: function () {
return <div>Component</div>
}
});

使用多个Mixin [__ 引入的顺序,决定了Mxins里生命周期方法的执行顺序。 __]

var AMixin = {
componentWillMount: function () {
console.log('AMixin Will Mount');
}
}; var BMixin = {
componentWillMount: function () {
console.log('BMixin Will Mount');
}
}; var Component = React.createClass({
mixins: [AMixin,BMixin],
componentWillMount: function () {
console.log('Component Will Mount');
},
render: function () {
return <div>Component</div>
}
});

不允许重复 [__ 除了生命周期方法可以重复以外,其他的方法都不可以重复,否则会报错 __]

不允许 Mixins 内的方法重复, 也不允许 Mixins 内的方法与组件的方法以及组件原型重复

换言之, __ 组件能访问到的方法不能被劫持 __

方法重复案例一

var AMixin = {
log: function () {
console.log('AMixin Log');
}
}; var BMixin = {
log: function () {
console.log('BMixin Log');
}
}; var Component = React.createClass({
mixins: [AMixin,BMixin],
render: function () {
return <div>Component</div>
}
});

方法重复案例二

var Mixin = {
log: function () {
console.log('Mixin Log');
}
}; var Component = React.createClass({
mixins: [Mixin],
log:function(){
console.log('Component Log');
},
render: function () {
return <div>Component</div>
}
});

HOC

如同 高阶函数, 高阶组件 也是一个函数, 你可以使用 typeof 进行检测, 从定义上来讲它就是一个地地道道的函数, 在 React 家族中我们叫它组件, 它接受一个组件, 返回一个新组件, 注意这里的组件本质上就是函数, 与 React 元素的概念上的区别见上一讲 React基础提升, 如果非要区分一下组件和函数的话, 那么组件是一种稍微特殊一点的函数, 它是构造函数, 但是 高阶组件 只是一个普通的函数, 从这层意义上讲, 高阶组件 并不是组件, 因为它不是构造函数, 只是一层 包装函数, 看一下 高阶函数 的大概面貌:

let HOC = BaseComponent => class extends React.Component {
// do something
render() {
return <BaseComponent />
}
};

这里的 HOC 是高阶组件, 并不是它的返回值是高阶组件, 它的返回值只是一个很普通的 React 组件

1

const HOCSomeComponent = SomeComponent => class extends React.Component {
render = x => <SomeComponent { ...this.props } />
}

** 可以做什么? **

操作 props

const HOCSomeComponent = SomeComponent => class extends React.Component {
render() {
let tel = { mp: '13194099515' };
return <SomeComponent { ...this.props } { ...tel } />;
}
}

包裹 SomeComponent

const HOCSomeComponent = SomeComponent => class extends React.Component {

	render() {
// 还可以传入多个组件
return (
<div>
<SomeComponent { ...this.props } />
</div>
)
}
}

2

反转继承

const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render = x => super.render()
}

** 还可以做什么? **

渲染劫持

条件渲染

const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render() {
if( someValue ) {
return super.render();
} else {
return null;
}
}
}

修改被包裹组件的输出树

const HOCSomeComponent = SomeComponent => class extends SomeComponent {
render() {
const ele = super.render();
let newProps = {};
if(ele[somekey] === someValue) {
newProps = { ... };
} const props = { ...this.props, ...newProps };
return React.cloneElement(ele, props, ele.props.children);
}
}

操作 state

const HOCSomeComponent = SomeComponent => class extends SomeComponent {
constructor(props) {
super(props);
this.state = Object.assign({}, this.state, { ... });
} render() {
return (
div>
{ super.render() }
</div>
)
}
}

...

{
... 不要限制你的思想, HOC 可以做很多...
}

React进阶篇学习的更多相关文章

  1. React进阶篇(1) -- react-router4模块化

    本篇内容: 单一的路由无嵌套 多层嵌套路由 获取路径中的参数 按需加载 单一的路由无嵌套 routers.js import Home from 'components/Home'; import N ...

  2. React进阶篇(2) -- Redux

    前言 如果还不知道为什么要使用Redux,说明你暂时还不需要它. 三大原则 单一数据源 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一 ...

  3. React基础篇学习

    到今天为止, 使用react已经一年了, 现在整理一下入门时的一些重要知识, 帮助想要学习react的同学们理解某些内容. React 元素 React 元素,它是 React 中最小基本单位,我们可 ...

  4. JavaScript学习笔记 - 进阶篇(1)- JS基础语法

    前言 JavaScript能做什么? 1.增强页面动态效果(如:下拉菜单.图片轮播.信息滚动等) 2.实现页面与用户之间的实时.动态交互(如:用户注册.登陆验证等) JS进阶篇学习什么? 在JavaS ...

  5. 4、JavaScript进阶篇①——基础语法

    一.认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面,但这还不够,它只是静态页面 ...

  6. JavaScript进阶篇 - -第1章 系好安全带

    第1章 系好安全带 html,body { font-size: 15px } body { font-family: Helvetica, "Hiragino Sans GB", ...

  7. PHP学习笔记 - 进阶篇(11)

    PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...

  8. PHP学习笔记 - 进阶篇(10)

    PHP学习笔记 - 进阶篇(10) 异常处理 抛出一个异常 从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被 ...

  9. PHP学习笔记 - 进阶篇(9)

    PHP学习笔记 - 进阶篇(9) 图形图像操作 GD库简介 GD指的是Graphic Device,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新 ...

随机推荐

  1. springboot pdf模板打印

    1.下载Adobe Acrobat DC工具来制作pdf的模板 打开一个pdf 2.制作pdf模板 把自动生成的文本框删除 然后 拖入文本框并自定义键 导入maven 依赖 <dependenc ...

  2. wx小程序知识点(八)

    八.小程序的优劣势 优势:   ① 不需要下载 ② 打开速度快 ③ 开发成本低 ④ 安卓上可以添加在桌面,与原生 App 相似 ⑤ 小程序的发布审查流程比较严格,安全保障 劣势:   ① 页面大小不能 ...

  3. Git 删除本地保存的账号和密码

    使用git在本地拉过一次代码时候git会自动将用户名密码保存到本地. 导致想用别的用户名和密码拉代码时没有权限,这时需要删除或者修改git在本地保存的账户名和密码. 具体办法如下: 1.控制面板--& ...

  4. 闰年计算——JavaScript 语言计算

    ㈠闰年是如何来的? 闰年(Leap Year)是为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差而设立的.补上时间差的年份为闰年. ㈡什么是闰年? 凡阳历中有闰日(二月为二十九日)的年, ...

  5. EasyUI DataGrid列表,显示undefined

    datagrid中,显示undefined的解决方法 在get函数中,将为null的值返回空的字符串 1 public class TestModel { 2 3 private String key ...

  6. CF603E Pastoral Oddities 优先队列+结论+LCT维护生成树

    首先,一个神奇的结论:一个合法的方案存在的条件是每一个联通块的节点数都是偶数个的. 这个可以用数学归纳法简单证一证. 证出这个后,我们只需动态加入每一个边,并查看一下有哪些边能够被删除(删掉后联通块依 ...

  7. matplotlib中plt.scatter()参数详解

    scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, l ...

  8. Spark译文(一)

    Spark Overview(Spark概述) ·Apache Spark是一种快速通用的集群计算系统. ·它提供Java,Scala,Python和R中的高级API,以及支持通用执行图的优化引擎. ...

  9. 安装破解confluence6.7.1(插图丢了,一直懒得补)

      JIRA安装:https://www.cnblogs.com/wei9593/p/10194784.html 1环境: centos7.2 java-1.8https://www.cnblogs. ...

  10. [JZOJ5399]:Confess(随机化)

    题目描述 小$w$隐藏的心绪已经难以再隐藏下去了. 小$w$有$n+1$(保证$n$为偶数)个心绪,每个都包含了$[1,2n]$的一个大小为$n$的子集. 现在他要找到隐藏的任意两个心绪,使得他们的交 ...