React.js:Virtual DOM,setState,propTypes

需求什么的停一停,我们来填一部分前面的坑。

React 的优势

又名:我为什么要学 React?React 牛逼在哪里?jQuery不是用的挺好吗?……

好处众说纷纭,我们来看一眼 React 官网首页给出的特性:

  1. Declarative
    React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.
    Declarative views make your code more predictable and easier to debug.
  2. Component-Based
    Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM.
  3. 一些其他我们现在不用关心的东西。

大部分优势已经很清楚了,不过 efficiently update and render 是怎么回事?

Virtual DOM

以上一篇案例中的列表来说,我们使用一个数组,存储了列表中所有需要显示的数据,当我们直接使用 JS 实现时,数据可能是下面这样:

var itemList = [{barcode:'ITEM000000',...},{barcode: 'ITEM000001'...},...];

如果,列表中的数据前后位置发生变化,比如,用户希望把优惠信息较多的商品显示在前面。emmm. 那我们就需要把 itemList 中的所有元素,按照这个规则进行排序,再使用排序后的数据,重新渲染整个页面。

sortWithPromotions(itemList);
itemListView.innerHTML = listToDOM(itemList);

这个 DOM 操作,貌似并没有花费掉多少运算能力。但是,朋友,DOM操作是很慢的。当页面中变动的元素数量稍稍多点的时候,就比较可怕了。

看一眼优惠信息:

barcodes: ['ITEM000000', 'ITEM000001', 'ITEM000005']

如果按照有优惠就在前的规则排序,仅仅需要交换ITEM000002ITEM000005 的位置就可以了。之前在 key 中也提到过,React 会高效的处理和渲染列表中的动态数据。

当页面中的数据发生变动时,React 并不会重新渲染 整个页面,而是在自己生成的 Virtual DOM 中,进行数据修改。再将 Virtual DOM 和真正的 DOM 做 对比,找出 发生变动的部分,并只将这部分内容渲染到页面中去。

听起来很有道理,而且听起来像骗人的,技术发展这么多年了,非要一直到 React 里才出现这种比对思想吗?而且,明明在操作原生 DOM 前还操作了虚拟 DOM,还做了对比,这难道真的还要比直接操作原生 DOM 效率要更高吗?

第一个问题,难点在比较两棵 DOM 树差异的 diff 算法的效率问题。
第二个问题,并不。只是在 React 中生成 Virtual DOM 、进行 diff 、渲染差异部分优化后的总时间,仍然比直接重新渲染整个页面的原生DOM操作时间少。当某天直接操作原生DOM够快时,那我们或许就不再需要 Virtual DOM 了。

setState

接下来,我们对之前的Counter做一个小小的改动,在点击事件中,count自增1之后,再立即自增1。

handleCountIncrease(event) {
    this.setState({count: this.state.count + 1});
    this.setState({count: this.state.count + 1});
}

点击一次后,可以看到Counter中显示的还是1。

之前我们并没有在点击事件中的处理方法中直接使用过这个值,所有到此为止并没有出什么问题。然而,可以感受到第二次自增中的 count 的值还没有变为1。如果count的默认值为0,相当于,我们将 count = 0 + 1 执行了两次。

为了提高性能,React 会 批量处理 state 的变更,而不是在发生一处改变之后就立即处理。这就会带来 异步 问题。如果需要立即使用这个值进行计算,可以把第二次需要立即使用state值的自增操作改为:

this.setState((prevState) => ({
    count: prevState.count + 1
}));

下面的写法效果是一样的:

this.setState(function(prevState) {
    return {
        count: prevState.count + 1
    };
});

propTypes

习惯了强类型语言,JS中对于类型的处理让我一直很不习惯。

抛去其他不说,在之前的组件<Item/>中,我们需要在使用时传入一个 Item 对象用于页面渲染。问题是使用这个组件的人,可能会随便传进来一个什么奇怪的东西,并且编译器也不会帮你检查,真是一点办法都没有。

emmm,其实是有办法的。
我们可以使用prop-types 库来限定每一个传入数据props的类型,安装一下。

npm install prop-types

比如最简单的限制item的类型为object,给Item.js稍稍增加一点代码:

import PropTypes from 'prop-types'
...
static propTypes = {
    item : PropTypes.object.isRequired
}

像代码里说的那样,我们在Item组件中要求item的类型为object,写法和设置默认值差不多。这样的类型以及不同的限定方式还有很多,可以在这里找到。

当我们传一个字符串'item'进去的时候,在控制台很容易找到问题:

今天就到这里了。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,139评论 25 707
  • 参考文章:深度剖析:如何实现一个Virtual DOM 算法 作者:戴嘉华React中一个没人能解释清楚的问题——...
    waka阅读 5,965评论 0 21
  • 1. 什么是React Router 一个基于 React 之上的强大路由库,官方的示例库有详细的使用介绍。 2....
    LYF闲闲闲闲阅读 509评论 0 2
  • 铃声响过一阵,拉着饭伴从闷热的教室离开。淅淅沥沥的小雨停了,谁也猜不准什么时候又开始。出了校门向左走。又是这条走过...
    厘九阅读 164评论 0 0
  • 开发中常遇到UI要求文本均匀分布,两端对齐,开始使用在文字中手动打空格的方式,但常常会碰到相同文字有时三个字,有时...
    清海浮生阅读 6,859评论 1 12