《深入React技术栈》笔记

有槽先吐

花了几天时间,大致读完了《深入React技术栈》,简单总结的话,不及预期。

作者成书前,在知乎开设pure render专栏,更新过一系列react主题文章。看过其中几篇,认为是内容很不错的文章,因此对成书期望很高,希望能在书中对react相关内容有一个真正全面深入的理解。

然而,在实际阅读过程中,总有一种茫然的感觉。个人感觉,书中所述,不见整体,陷入细节。

第三章《解读React源码》,书中内容缺少对React整体设计的解构,很快的陷入到细节中,附上一些具体实现的源码。对于一个本身相对复杂的内容,这种写法读完会觉得摸不着头脑。

写博文和写书应当是两种写作方法,专栏中的文章,基于作者分享知识,大家的要求不会太高,有一点收货都会满意。出版成书,就不能只是将博文整理成册了,读者对于书的期望,显然是比博文更高。

一些收获

作者对react技术栈,应该是有深入的理解的,不太认可的,是这本书的表述方式。读过一遍,也有一点收获。

合成事件与原生事件混用的问题

想实现页面中有一个二维码,点击二维码不隐藏,点击二维码以外地方,隐藏二维码的功能

//为body绑定原生click
componentDidMount(){
document.body.addEventListener('click',e=>{
  this.setState({active:false})
})
}

//合成事件
handleClickQr(e){
  e.preventDefault();
}

render(){
  return (
    <div classname='code' style={{display:this.state.active ? 'block' : 'none'}} onclick = {this.handleClickQr}>
      ![](qr.jpg)
    </div>
  )
}

预期点击二维码时,阻止默认事件,不隐藏二维码。实际效果是点击二维码区域,也会导致隐藏。原因是React合成事件系统的委派机制,事件并没有绑定到div.qr元素上。

解决方法有两个

  • 不要将合成事件与原生事件混用
componentDidMount(){
  document.body.addEventListener('click',e=>{
    this.setState({active:false})
  });
  
  document.querySelector('.qr').addEventListener('click',e=>{
    e.preventDefault();
  })
}
  • 通过事件对象e.target判断
componentDidMount(){
  document.body.addEventListener('click',e=>{
    if(e.target && e.target.matchs('div.code')){return}
    this.setState({active:false})
  });
}

理解setState机制

class Example extends Component {
  constructor(){
    super();
    this.state={val:0};
  }

  componentDidMount(){
    this.setState({val:this.state.val+1});
    console.log(this.state.val);//第一次输出

    this.setState({val:this.state.val+1});
    console.log(this.state.val);//第二次输出

    setTimeout(()=>{
      this.setState({val:this.state.val+1});
      console.log(this.state.val);//第三次输出

      this.setState({val:this.state.val+1});
      console.log(this.state.val);//第四次输出
    },0)
  }
}

上述代码,分别输出:0、0、2、3

理解原因,需知setState机制。

  • setState 底层批量更新
  • 批量更新过程由事务控制
  • 前两次setState,整个react组件渲染到DOM的过程已经处于一个大的事务中,batchingStrategy的isBatchingUpdates已经被设为true,所以两次setState的结果并没有立即生效,而是被放进了dirtyComponents中。
  • setTimeout中执行的两次setState,因为与初始react组件渲染过程在不同的事件循环,没有前置的batchedUpdate调用,batchingStrategy的isBatchingUpdates标志位是false,使得新的state立即生效。

redux应用的架构

一个典型的redux应用结构是类型下面

在一些功能简单的应用中,可以像上面这样按照类型划分文件结构。但是在大型应用中,会存在很多组件,如果仍以类型划分,会导致如actions目录下,有非常多的action.js文件,很难快速定位文件。因此在大型应用中,可以采用混合方式划分文件结构。

在上述结构中,首先将redux中的组件,划分为了三种不同的组件,Layouts、Views、Compoents

  • Layouts是页面布局组件,描述页面的基本结构,目的是将主框架与页面主体内容分离

const Layout = ({children}) => (
<div classname = 'container'>
<Header/>
<div classname = 'content'>
{children}
</div>
</div>
)

* Views是子路由入口组件,描述子路由入口基本结构,包含此路由下所有展示型组件。为了保持子组件的纯净,我们在这一层组件中定义数据和action的入口,将他们分发到子组件中去。Views就是Redux中的容器型组件

@connect(state => {
...
})
class HomeView extends Component {
render(){
const {sth,changeType} = this.props;
const cardProps = {sth,changeType};
return (
<div>
<Card {...cardProps}/>
</div>
)
}
}

* Components就是末级渲染组件,包含了具体的业务逻辑和交互,但是所有的数据和actions都是从Views传下来的,意味着它们可以完全脱离数据层而独立存在的展示型组件。

class Card extends Components {
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
}

handleChange(opts){
const {type} = opts;
this.props.changeType(type);
}

render(){
const {sth} = this.props;
return (
<div>
<Switch onChange = {this.handleChange}>
...
</Switch>
{sth}
</div>
)
}
}


理解了三种类型组件,再来看views/和componets文件夹。views文件夹中,存放的每个路由的入口页,如首页(Home)。每一个入口都会有三个文件,*.js是入口组件,*.css是样式,*Redux.js是components/Home文件夹下所有reducer和action的聚合。

在components/Home文件夹里,是当前路由对应的页面Home需要的所有内容--components、actions、reducers、样式等。

views/HomeRedux.js示例

import { combineReducers } from 'redux';
// 引入 reducer 及 actionCreator
import list, { loadArticles } from '../components/Home/PreviewListRedux';
export default combineReducers({ list,});
export const actions = { loadArticles,};


components/Home/PreviewListRedux.js示例

const initialState = {
loading: true,
error: false,
articleList: [],
};

const LOAD_ARTICLES = 'LOAD_ARTICLES';
const LOAD_ARTICLES_SUCCESS = 'LOAD_ARTICLES_SUCCESS';
const LOAD_ARTICLES_ERROR = 'LOAD_ARTICLES_ERROR';

export function loadArticles() {
return {
types: [LOAD_ARTICLES, LOAD_ARTICLES_SUCCESS, LOAD_ARTICLES_ERROR],
url: '/api/articles.json',
};
}

export default function previewList(state = initialState, action) {
switch (action.type) {
case LOAD_ARTICLES: {
return {
...state,
loading: true,
error: false,
};
}

case LOAD_ARTICLES_SUCCESS: {
  return {
    ...state,
    loading: false,
    error: false,
    articleList: action.payload,
  };
}

case LOAD_ARTICLES_ERROR: {
  return {
    ...state,
    loading: false,
    error: true,
  };
}

default:
  return state;

}
}


**如果觉得有帮助,可以扫描二维码对我打赏,谢谢**
![](http://upload-images.jianshu.io/upload_images/2898168-9262d2444b223aa5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • 一、初入React世界 1.2 JSX语法 class 属性修改为className for 属性修改为 htmF...
    不安分的三好份子阅读 2,164评论 0 4
  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,758评论 0 24
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,532评论 14 128
  • 9.17星期日晴(156) 今天去书店买书,儿子买了一本数独游戏的书,之前看到五年级的同学玩过,也不知儿子...
    王界程阅读 149评论 0 0
  • 很长一段时间没有写文章了,这篇文章写于昨天下午,那时的我正坐在海口市中心一家餐厅的窗边,眺望着这个弥漫着风情的城市...
    卓文业阅读 273评论 0 1