• 使用pureRender,setState和Immutable.js来操作state

Immutable 中文意思不可变。

不能直接修改state的值,要用setState 和Immutable

react 官方要求不要直接修改state,比如this.state.name = "suyuan"是错误的写法,应该用this.setState({name, "suyuan"});

原因1.其实state并不是不可变的,官方是希望你把他当做不变来用,因为只有setState的时候才会发生消息给react 来re-render,this.state.name="bianhua" 不会引起re-rener;

原因2.本来不管你数据有没有变化, setState就一定会重新渲染,为了提高性能一般会引去pureRender技术(本文其他章节有描述),该技术是进行浅比较(根节点的地址),p1,p2,p3

假如你这样错误的写:

let p1=state.p1;

p1.name = "bianhua";

this.setState({p1:p1});

用了pureRender技术后,react 发现p1没有变化(p1的地址没变,不是新对象),也不会re-render

所以你应该这样写

let p1=JsFrom(state.p1);

p1.name = "bianhua";

this.setState({p1:p1});

这篇文章描述了immutable

https://zhuanlan.zhihu.com/p/20295971?columnSlug=purerender

使用PureRenders

Example Mixin 混入类s:

var PureRenderMixin = require('react-addons-pure-render-mixin');
React.createClass({
mixins:[PureRenderMixin],
render: function() {
return <div className={this.props.className}>foo</div>;
}
});

Example using ES6 class syntax:

import PureRenderMixin from 'react-addons-pure-render-mixin';
class FooComponent extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate=PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return <div className={this.props.className}>foo</div>;
}
}

或者用pure-render-decorator 装饰器

import {Component} from 'react';

import pureRender from 'pure-render-decorator';

@pureRender
export default class Test extends Component {
render() {
return <div />;
}
}

a. 优化了性能

PureRenderMixin 重写了shouldComponentUpdate,只有在props或者state真正改变的时候才会重新render,这个在react性能上是一个优化,从此以后你可以大胆的setState,而不需要写这样的代码

if (this.state.someVal !== computedVal) { // 判断是否需要setState,因为每次setState都会引起render,不管你的数据是不是真的变化了

    this.setState({someVal: computedVal})

}

b.有一点要注意,继承PureRenderMixin要求render 必须是纯函数,当然本来react官文就说render should 纯函数,这里跟需要时纯函数,为什么?

b.1.单纯react来讲,页面和state直接反应,如果render不是纯函数,就会导致页面展示和state对不上号,还有去查询其他关联数据;

b.2.从继承混入类来说,如果你写了下面这种不纯的代码

render: function () {

    //…

    if (this._previousFoo !== this.props.foo) { // <-- IMPURE

        return renderSomethingDifferent();

    }

}

依赖了一个其他变量this._previousFoo,就会引入bug;

>本来不用混入类,你setState后就算state不改变,也会render,然后再render过程中this._previousFoo的数据变化可能导致页面发生变化;

>现在引入混入类,完蛋了,setState后,state数据不变也就不会render了,页面不变了,和你希望的不一样了。

所以render要纯正,除非上面this._previousFoo 你保证永远不变,是个const

c 还有个重要的事情要说,我觉得太重要了,PureRenderMixin混入类 只会进行浅比较,就是C++里面的指针(地址比较),如果你修改了一个数组的某个item,你其实是希望render的,但是PureRenderMixin 认为数组的地址没变,数组也就没变,也就没render;怎么办?

c.1.组件创建新对象--切片 array.silce()

c.2.object创建新对象-- var copy = Object.assign({}, obj);

c.3.react 自带的操作数据的方式 https://facebook.github.io/react/docs/update.html

c.4..第三方库Immutable.js 和 mori

这里有个坑,用了purRender有时候无效,比如组件下面包含了子组件的时候,this.props.children 就算数据不变,对象也不是原来的对象的,为了优化某个组件的性能我还特意重写了shouldComponentUpdate,把props.children 排除了,这个可能是purRender的原则,看了下源代码完全没搞明白,所以假如render不纯的话(比如使用了this.name)我估计还是会重写渲染,有兴趣会试验一下

这里插入一句,redux中的mapToState() 做为reducer和Component的桥梁,reducer 在返回newState后虽然肯定会执行mapToState,但是mapToState中return出去的数据{xkey:xvalue},如果xvalue的地址没有改变,mapToState关联的Component也不会render;

适当的使用context,方便给子组件传变量

父组件给子组件上下文定义个变量,子组件声明这个变量,就可以使用;

方便数据传递,不需要通过props一层层塞进去

// ------Component A

class A extends React.Component {

// add the following property

static childContextTypes = {

  user: React.PropTypes.object.isRequired

}

// add the following method

  getChildContext() {

    return {

      user: this.props.user  //children 组件可以使用this.context.user

    }

  }

  render() {

    <div>{this.props.children}</div>

  }

}

// -----Component D

class D extends React.Component {

// add the following property

static contextTypes = {

  user: React.PropTypes.object.isRequired

}

  render() {

    <div>{this.context.user.name}</div>

  }

}

或者

function D(props, context) {

  return (

    <div>{this.context.user.name}</div>

  );

}

D.contextTypes = {

  user: React.PropTypes.object.isRequired

}

使用propTypes 和defaultProps

class Greeting extends React.Component {

  static propTypes = {
name: React.PropTypes.string
} static defaultProps = {
  name: "suyuans"
} render() { return ( <h1>Hello, {this.props.name}</h1> ); } }

React 可以帮你检测传入的props是否有误,自己在使用组件时候也会更清晰需要传入什么props

不过要记得在编译线上版本的时候设置环境变量NODE_ENV="production",避免影响线上的性能

减少操作state

所有的编程语言在写代码的过程中,都希望是无状态的,纯函数的方式;

React 提供了setState 接口,但是我们还要是减少他的使用;

如果state使用不好可能导致组件复杂混乱,re-render 失控;

比如在 componentDidMount() or componentDidUpdate()生命周期中使用setState1是控制不好可能发生死循环,2是加入子组件也类似的使用,子子组件等刷新的次数会成2的幂次方增加;

不过使用state是必不可少的,但是一定要封装好state,确保只有本组件可见;

假如父组件需要知道一些关于子组件的state,这就破坏了组件的结构,意味着组件的抽象失败,可以需要对该组件重构

集中管理state

在工作中,父组件需要知道子组件的state或者信息是必不可少的,一般我们把state完全集中在一个地方(一般最顶层)控制,

父组件通过props向子组件传递信息,

这就是Flux 架构模型:用集合仓库来管理state,用action事件来驱动state的更新,这时候state的存储和操作都是原子性的,任何state的变化都会去重新渲染组件,以达到单向数据流的目的;

意思就是所有组件都依赖props渲染数据,数据源全部来自数据中心state,组件通过 事件、管道、回调、方法、stream来和数据中心通信。

这个看起来有点低效,但是react所倡导的就是 js的速度很快和虚拟dom diff的思想;

纯props的组件库会更好的发挥purRender相关的优势;

缺点是 会使得原来一些简单的通过setSate的事情变的麻烦了,但是优点是单向数据流更直观的反应了我们的应用。

这种思想就像flux架构,见下图

一旦数据中心store 数据变更了,他就render组件,组件会向子组件传递变更的数据

说白了,组件就是处理props 到 页面的纯函数,这样的组件也更容易使用和测试, 组件正常的展示,正常触发事件,触发事件后store数据更新正常 就表明组件一切ok。

如果组件之间通过回调函数来操作,组件之间的耦合性就太高,需要知道对方的一些数据、接口、函数,这样抽象就失败了,应该通过action的方式相互通讯。

尽量把代码写在render中

尽量把componentWillReceiveProps or componentWillMount 下面的代码写到render中,

把一些处理props,或者计算setState的处理函数写到render

永远不要担心js的速度,这样写的好处很多,减少bug并容易发现bug,减少重复代码等

// bad

componentWillMount: function () {

    this.setState({

        computedFoo: compute(this.props.foo)

    });

},

componentWillReceiveProps: function (nextProps) {

    this.setState({

        computedFoo: compute(nextProps.foo)

    });

},

render: function () {

    return React.DOM.div({className: this.state.computedFoo});

}

// better

render: function () {

    var computedFoo = compute(this.props.foo);

    return React.DOM.div({className: computedFoo});

}

也可以在render 中计算获取其他的组件,在render 做更多的事情,当然也不要把render搞的太长太大

MIXIN 或者extend 非常好用

可以用他们来创建复用的功能块

PureRenderMixin  就是覆盖了shouldComponentUpdate() 方法

你可能有疑问了,生命周期componentWillMount之类的继承下来不就遭了,有的我不需要是不是要重写个空的?放心,mixin特意把生命周期排除出去啊,哈哈 机智啊

比如我们可以把处理state的逻辑放到mixin中,就算只有一个组件只用也ok,这样可以保证组件内部的无状态性,通过mixin 来构建有状态的组件,以后你可以通过修改mixin来更换功能,复用这个组件,mixin这时候有点control层的角色扮演,不过小心的是mixin要被抛弃了,用extend把

使用类实例的属性

尽管组件应该是以props为参数的纯函数,但是有时候使用实例属性也是明智的。

有时候this.foo比this.props.foo要更合适;要注意的是PureRender 的时候render下不要这样使用,原因看之前的内容。

如果这个数据不影响页面的呈现,这样用是非常方便的

 

componentWillReceiveProps: function () {

    this._timer = Date.now();

},

onLoadHandler: function () {

    this.trigger("load:time", Date.now() - this._timer);

},

render: function () {

    return React.DOM.img({

        src: this.props.src,

        onLoad: this.onLoadHandler

    });

}

上面用一个实例属性来存放开始时候,以计算load时间,这个时间变化后我也不需要页面展示渲染,所以可以放在实例属性中。

一句话,数据变化了,页面不需要刷新变化的,可以作为实例属性

数据变化,页面变化的那就是state了

组件通信

父到子  1.props, 2.ref

子到父  1.回调函数this.props.callback()

兄弟   1.通过父绕一圈,2.采用第三方消息系统如js-signals: https://github.com/millermedeiros/js-signals

一切通信,如果用了flux或者redux就解决了

下面是一些js使用建议

1.遵循es6严格模式

2.声明变量的优先级 const、let

3.箭头函数代替繁杂的bind

4.可以引用typescript减少bug,当然用了严格模式也足够了

推荐个组件库 antd

推荐使用redux(control、modal层) 管理react(view层s)

本文参考了

React建议:http://aeflash.com/2015-02/react-tips-and-best-practices.html

immutable使用:

https://zhuanlan.zhihu.com/p/20295971?columnSlug=purerender

https://www.w3ctech.com/topic/1595

react 使用的小建议的更多相关文章

  1. extjs 优化小建议

    1 原文信息 原文标题: Sencha Con 2013: Ext JS Performance tips 原文地址: [http://edspencer.net/2013/07/19/sencha- ...

  2. 有用的JavaScript开发小建议

    这篇文章将向你分享一些不为人知的但很有用的JavaScript小建议,对那些刚涉及使用JavaScript编程语言的初级开发者应该有很大的帮助. 1. 用数组长度截取数组 我们都知道,对象都是通过使用 ...

  3. 在JAVA中记录日志的十个小建议

    JAVA日志管理既是一门科学,又是一门艺术.科学的部分是指了解写日志的工具以及其API,而选择日志的格式,消息的格式,日志记录的内容,哪种消息对应于哪一种日志级别,则完全是基于经验.从过去的实践证明, ...

  4. react与微信小程序

    由组员完成 原文链接 都说react和微信小程序很像,但是像在什么部分呢,待我稍作对比. 生命周期 1.React React的生命周期在16版本以前与之后发生了重大变化,原因在于引入的React F ...

  5. Python入门小建议

    "java从心"正式更名"KEN DO EVERTHING".Ken(Can) Do Everything,无所不能 Believe youseft then ...

  6. Docker 部署 redis教程,附带部分小建议,防止踩坑

    Docker 部署 redis,附带部分小建议,防止踩坑 跟所有人一样,我们先从docker基本命令开始 一.拉取redis镜像(配图来自菜鸟,其实截图没多大意义,对比看下) # 默认就拉取laste ...

  7. 微信小程序--关于加快小程序开发的几个小建议

    加快小程序开发的几个小建议 1.使用 app.json创建页面 ​ 按照我们平常的开发习惯,创建一个新的页面,一般都会先创建文件夹,再创建对应page的形式,创建完成后,app.json中会自动注册该 ...

  8. redis优化小建议

    1.优化的一些小建议 1.尽量使用短的key 当然在精简的同时,不要为了key的"见名知意".对于value有些也可精简,比如性别使用0.1. 2.每个redis设置合理内存 每个 ...

  9. React Native工作小技巧及填坑记录

    以下是本人在React Native开发工作中使用的一些小技巧,记录一下. 1.从网络上拉取下来的React Native缺少React和React Native库. 终端 1. cd 项目根目录 2 ...

随机推荐

  1. [转]【response】HttpServletResponse接口

    创建时间:6.19 & 6.24 1.HttpServletResponse概述 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参 ...

  2. ValueError: Dependency on app with no migrations: customuser

    You haven't run manage.py makemigrations customuser to create the migrations for your CustomUser app ...

  3. Comet OJ 夏季欢乐赛 分配学号

    Comet OJ 夏季欢乐赛 H 分配学号 题目传送门 题目描述 今天,是JWJU给同学们分配学号的一天!为了让大家尽可能的得到自己想要的学号,鸡尾酒让大家先从 [1,10^{18}][1,1018] ...

  4. Flask视图之CBV示列

    from flask import views, Flask app=Flask(__name__) class loginview( views.MethodView ):   # 继承views. ...

  5. UNIX网络编程卷1 - >环境搭建(ubuntu16.04)

      学习unp网络编程,树上的例子均存在#include“unp.h”,故需要对环境进行配置. 1.到资源页下载www.unpbook.com 2.解压并将unpv13e移动到相应的文件夹下 (因为我 ...

  6. 洛谷p2827蚯蚓题解

    题目 算法标签里的算法什么的都不会啊 什么二叉堆?? qbxt出去学习的时候讲的,一段时间之前做的,现在才写到博客上的 维护3个队列,队列1表示最开始的蚯蚓,队列2表示每一次被切的蚯蚓被分开的较长的那 ...

  7. 格利文科定理(Glivenko–Cantelli Theorem)

    格利文科定理:每次从总体中随机抽取1个样本,这样抽取很多次后,样本的分布会趋近于总体分布.也可以理解为:从总体中抽取容量为n的样本,样本容量n越大,样本的分布越趋近于总体分布. (注:总体数据需要独立 ...

  8. Springboot之自定义配置

    SpringBoot自定义配置 springboot在这里就不过多介绍了,大家都应该了解springboot零配置文件,所以配置信息都装配在属性文件(properties.yml.yaml)中,有时我 ...

  9. nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件

    前言一.nginx简介1. 什么是 nginx 和可以做什么事情Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50 ...

  10. tomcat Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

      1.情景展示 tomcat 日志时不时会报出如下异常信息,到底是怎么回事? java.lang.IllegalArgumentException: Invalid character found ...