react知识点梳理

1.immutable

连续看了两三篇关于immutable.js的文章,传统的object和array等引用类型是mutable数据,就是当赋值的时候,指向同个内存,这在react更新机制里面就会出现个问题,引用是相同的,react purecomponent就会检测不出前后两个props的不同部分,就不会re-render,而React.Component是可以检测出来props的更新的,然后就会re-render,比如一个组件的props改变(数据流是单向的)该组件的props改变只需要其对应的父组件更新就可以了,不需要该组件的兄弟组件及其子组件更新,因为原生js引用类型共享内存,这些组件都会更新,这是我们不想看到的,所以引入了immutable.js共享部分内存,把直接相关的节点更新就可以了。

Immutable.js 以及在 react+redux 项目中的实践
react Performance Tools 入门
使用immutable优化React

2. 模块或者组件按需加载

React Loadable 简介
webpack 构建性能优化策略小结
react项目优化之webpack
react-router按需加载(V4版)

使用import()实现组件的按需加载

根据点击的链接会在head标签里插入



发现个很有趣的现象,点击About链接或者DashBoard链接两个组件相互切换,在同个页面的路由组件,路由切换的话,前面一个渲染好的组件会Unmount,即被卸载
例如路由about->dashboard,About组件会被卸载(componentWillUnmount被调用),DashBoard被装载(componentWillMount被调用),


由下图可以看出,路由导航到dashboard的时候About组件并没有被包含在其Route组件里,也就是切换路由的时候About被卸载了,移出了dom

仓库:assassin / react-starter

参考:

在react-router4中进行代码拆分(基于webpack)
HTML5 <script>元素async,defer异步加载

3.试读react-redux源码

本文的react-redux代码本版为5.0.6

阮一峰的Redux 入门教程(三):React-Redux 的用法

class VisibleTodoList extends Component {
  componentDidMount() {
    const { store } = this.context;
    this.unsubscribe = store.subscribe(() =>
      this.forceUpdate()
    );
  }

  render() {
    const props = this.props;
    const { store } = this.context;
    const state = store.getState();
    // ...
  }
}

VisibleTodoList.contextTypes = {
  store: React.PropTypes.object
}

React-Redux自动生成的容器组件的代码,就类似上面这样,从而拿到store
这句话不是很理解,对比了下官方给出的代码:

import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case 'SHOW_ALL':
      return todos
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed)
    case 'SHOW_ACTIVE':
      return todos.filter(t => !t.completed)
    default:
      throw new Error('Unknown filter: ' + filter)
  }
}

const mapStateToProps = (state) => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
})

const mapDispatchToProps = {
  onTodoClick: toggleTodo
}

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

export default VisibleTodoList

和大神说的自动生成的容器组件的代码完全不同,现在的理解应该是connect以后得到的容器组件的代码,而不是现在我们看到的官网的容器组件的代码

今天看到了connectAdvanced.js的最后一句卡住了return hoistStatics(Connect, WrappedComponent)
import hoistStatics from 'hoist-non-react-statics'来自于hoist-non-react-statics具体干啥用的还不清楚,搜索它怎么用的时候发现了官网高阶组件里面提到了这个库,于是再次看了遍高阶组件的用法,如是说:高阶组件是一个函数,能够接受一个组件并返回一个新的组件,结合实际的react-redux的connect功能,

import TodoList from '../components/TodoList'
const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

connect.js


connect.js

connect.js调用了connectAdvanced.js
connectAdvanced.js


connectAdvanced.js
connect()(TodoList)返回的新组件

那么如果从高阶组件的定义高阶组件是一个函数,能够接受一个组件并返回一个新的组件来看connectAdvanced.js中的wrapWithConnect函数就是高阶组件,它接受了一个WrappedComponent组件返回了一个<Connect(TodoList)>...</Connect(TodoList)>新的组件

displayName其实是组件的一个静态属性,如果在组件中定义则有,否则不会有该属性
静态属性在es6的不同版本有不同的定义方式:

export default class MainSection extends Component {
  static propTypes = {//先进的一种
    todos: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired
  }
}
//原始的一种
MainSection.propTypes={
    todos: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired
}

到目前的理解,使用高阶组件的目的有

  • 抽取很多组件的公共方法和属性,类似于之前的mixin
  • 返回的新组件必须保留原始组件的功能(包括原始组件的静态方法和静态属性)
    connectAdvanced.js
import hoistStatics from 'hoist-non-react-statics'

export default function connectAdvanced(){
  return function wrapWithConnect(WrappedComponent) {
    class Connect extends Component {
   }

    Connect.WrappedComponent = WrappedComponent
    Connect.displayName = displayName
    Connect.childContextTypes = childContextTypes
    Connect.contextTypes = contextTypes
    Connect.propTypes = contextTypes

    if (process.env.NODE_ENV !== 'production') {
    }

    return hoistStatics(Connect, WrappedComponent)//原始组件的所有静态方法全部拷贝给新组件
  }
}
}

上下文(Context)
react-redux源码分析
react-redux源码分析
react-redux 源码解析

一个有意思的发现:

class Animal{
  constructor(){
    this.age=""
  }
  showAge(){
    console.info(this.age)
  }
  getName=()=>{
    return "name"  
  }
}

使用ts编译为js

var Animal = /** @class */ (function () {
    function Animal() {
        this.getName = function () {
            return "name";
        };
        this.age = "";
    }
    Animal.prototype.showAge = function () {
        console.info(this.age);
    };
    return Animal;
}());

4.高阶组件的两种实现方式

看这篇文章带着三个问题一起深入浅出React高阶组件的时候发现有个有趣的现象:父组件可以直接调用子组件的实例方法,这在Java中是不可能的,具体可查看Java 中父类怎么调用子类的方法?,这篇文章指出可以使用反射的方式,js真的不按套路出牌啊

深入理解 React 高阶组件
React进阶之高阶组件
React高阶组件探究
React 高阶组件(HOC)入门指南

5.木偶组件和智能组件

在 2017 年学习 React + Redux 的一些建议(上篇)

react root组件下面应该放什么组件?

6.按需加载 包括saga

react结合redux和react-router开发大型应用实现按需加载(code spliting)
React Router v4 之代码分割:从放弃到入门

7.在代码提交之前需要对代码进行lint和语法检查

需要用到库:
okonet/lint-staged
typicode/husky
prettier/prettier

从React脚手架工具学习React项目的最佳实践(上):前端基础配置
前端开发如何让持续集成/持续部署(CI/CD)跑起来

github 集成测试
前端开源项目持续集成三剑客

8.用js的方式改变子组件的props
import RadioButton from './radioButton'
children = React.Children.map(children, (child: any) => {
        if (child.type === RadioButton) {
          return React.cloneElement(child, {
            prefixCls: radioType === 'text' ? 'radio-text' : 'radio-button', //手动改变了prefixCls props
          })
        } else {
          return child
        }
      })

React中props.children和React.Children的区别

9. 在生产环境中使用LogRocket记录Redux日志
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容