腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的是房价,很明显,人类对 React 的关注程度已经远远超过了对房价的关注。 从这些数据中,大家能看出什么? 从2014年到现在,React、jQuery和 Angular 的热度趋势对比,可以很明显的看到(上图),React 在全球的热度趋势增长非常快。 上图是 React 在国内的百度搜索指数,是拿 React 和 Nodejs 做了个对比,可以看出 React 的关注度也已经逼近 nodejs。 虽然在关注总量上 React 还远不及 jQuery 和 Angular 等等,但它的增长幅度超乎你想象,你知道这意味着什么吗?这意味着关注 React,你就比大多数人走在了业界的前沿! 那么React到底是什么鬼? 引用官网的简介,”一个用来构建用户界面的javascript库”。 React 起源于 Facebook 的内部项目,因为 FB 对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。 由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。 和 Backbone、Angular 等 MV* 框架不一样,它只处理 View 逻辑 ,它只处理 View 逻辑,它只处理 View 逻辑。所以如果你喜欢它,你可以很容易的将它接入到现有工程中,然后用 React 重写 HTML 部分即可,不用修改逻辑。 近几年 web 领域的技术革新非常迅速,React也是一项新技术…话说React出来也已经2年了,其实并不算什么新技术了,只是在国内还没有普及开,这篇文章的目的也是帮助大家更快的理解 react 和认识 react 能给我们带来的价值。 React 这么火,那么它到底有什么牛逼的地方? 上图是2015年年初的数据 这是 Facebook 的好友动态页面,也是 Facebook 访问量最大的页面没有之一,通过 Chrome React 插件可以看到这个页面确实是用 React 实现的。 (有同事问我为什么关注柳岩,我说因为我是柳岩的球迷啊) 前面给大家来了一波前戏,相信大家已经有点迫不及待了,那么,进入正题: 首先,先跟大家描述下 React 最特别的部分,听完这部分大家基本就能够在脑海里建立起一个 React 的大致印象。 然后是 React 的核心内容,听完这部分大家待会回去就可以开始写代码然后今天晚上发布上线了。 最后是 React 能够给我们实际带来的价值,我们不作无意义的代码重构。 首先,我们来看JSX—— JSX 使用的是预编译模板,React 提供了一个预编译工具,叫 react-tools,可以通过 npm 命令安装,一般是在开发时期运行,运行后它会启动一个监听程序,实时监听 JSX 源码的修改,然后自动编译为 JS 代码。 大家留意下,render() 方法里的被编译成了 React.createElement(),它这么做,目的就是为了实现虚拟 DOM。 接下来我们来了解 React 最大的亮点 ———— 虚拟 DOM。 传统 web app 和 DOM 直接交互,由App来控制DOM的构建和渲染、元素属性的读写、事件的注册和销毁等等。 当新产品刚上线的时候,这种做法看起来也挺好。但随着产品功能越来越丰富、代码量越来越多、开发团队人员越来越多 ————— 一年后 你的代码可能会变成这样。 当然,合理的代码规划能够避免这类问题,但团队里难免会有擅长屠宰式编程的同学,分分钟把你代码改的面目全非。 这时,React的虚拟DOM和单项数据流就能很好的解决这个问题。 虚拟DOM则是在DOM的基础上建立了一个抽象层,我们对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中。 虚拟DOM会使得App只关心数据和组件的执行结果,中间产生的DOM操作不需要App干预,而且通过虚拟DOM来生成DOM,会有一项非常可观收益——-性能。 所有人都知道DOM慢,渲染一个空的DIV,浏览器需要为这个DIV生成几百个属性,而虚拟DOM只有6个,所以减少不必要的重排重绘以及DOM读写能够对页面渲染性能有大幅提升。 那么我们来看看虚拟DOM是怎么做的:React会在内存中维护一个虚拟DOM树,当我们对这个树进行读或写的时候,实际上是对虚拟DOM进行的。当数据变化时,然后React会自动更新虚拟DOM,然后拿新的虚拟DOM和旧的虚拟DOM进行对比,找到有变更的部分,得出一个Patch,然后将这个Patch放到一个队列里,最终批量更新这些Patch到DOM中。 这样的机制可以保证即便是根节点数据的变化,最终表现在DOM上的修改也只是受这个数据影响的部分,可以保证非常高效的渲染。 但这样也是有一定的缺陷的——首次渲染大量DOM时因为多了一层虚拟DOM的计算,会比innerHTML插入方式慢,所以使用时需要确保不要一次性渲染大量DOM。 几个UI组件的渲染性能对比 http://mathieuancelin./js-repaint-perfs/ 一个最基本的 React 组件由数据和JSX两个主要部分构成,我们先来看看数据。 这是一个简单单完整的React组件【类】,细节大家先不用太在意细节,了解机制就可以。 props 主要作用是提供数据来源,可以简单的理解为 props 就是构造函数的参数。 state 唯一的作用是控制组件的表现,用来存放会随着交互变化状态,比如开关状态等。 JSX 做的事情就是根据 state 和 props 中的值,结合一些视图层面的逻辑,输出对应的 DOM 结构。 前面我们知道了一个简单的组件的构成,但单个的组件肯定不能满足实际需求,我们需要做的是将这些独立的组件进行组装,同时找出共性的部分进行复用。 比如这样一个场景 我们以这样一个界面为例,可以看出,里面的 <Pub/> <Article/> 都是最细粒度的组件,是可以复用的。 首先,我们来看下Article的代码—— 这个就是我们分解出来的 Article 组件,它需要2个属性,article对象和showImage。article对象包含图片、地址、标题、描述信息,showImage是一个布尔类型,用来判断是否需要显示成一个图片。 这个组件本身的实现可以很简单也可以很复杂,但使用者可不关心你的内部实现,使用者关心的是组件需要什么参数就可以了。 外国人的组件化思想比我们国内的普及程度高很多,不只局限于软件开发,包括实体行业的咖啡机、加油站、 儿童摇摇车都有这种设计思想在里面。 希望大家在设计模块的时候,也尽可能将组件逻辑对外透明,来减少维护成本。 大家留意一下标虚线的部分,这里复用了 Article 组件。这时的 Article 组件看起来就是一个普通的标签而已,简单吧。 这个是热问组件,也复用了 Article 组件。这就是 React 如丝般顺滑的组件复合。 这个,叫做竹笕,是中日传统禅文化中常见的庭院装饰品,它的构造可简单可复杂,但原理很简单,比如这个竹笕,水从竹笕顶部入口流入内部,并按照固定的顺序从上向下依次流入各个小竹筒,然后驱动水轮转动。对于强迫症患者来说,观赏竹笕的绝对是一种很享受的过程的最爱,你会发现这些小玩意竟然能这么流畅的协调起来,好神奇。 如果竹笕是一个组件的话,那么水就是组件的数据流。 在React中,数据流是自上而下单向的从父节点传递到子节点,所以组件是简单且容易把握的,他们只需要从父节点提供的props中获取数据并渲染即可。如果顶层组件的某个prop改变了,React会递归地向下遍历整棵组件数,重新渲染所有使用这个属性的组件。 这个是前面看到的 Article 题组件,拥有一个叫做 articles 的属性。 在组件内部,可以通过this.props来访问props,props是组件唯一的数据来源,对于组件来说: props永远是只读的。 组件的属性类型如果不进行声明和验证,那么很可能使用者传给你的属性值或者类型是无效的,那会导致一些意料之外的故障。好在React已经为我们提供了一套非常简单好用的属性校验机制—— React有一个PropTypes属性校验工具,经过简单的配置即可。当使用者传入的参数不满足校验规则时,React会给出非常详细的警告,定位问题不要太容易。 PropTypes包含的校验类型包括基本类型、数组、对象、实例、枚举—— 以及对象类型的深入验证等等。如果内置的验证类型不满足需求,还可以通过自定义规则来验证。 如果某个属性是必须的,在类型后面加上 .isRequired 即可。 React的一大创新,就是把每一个组件都看成是一个状态机,组件内部通过state来维护组件状态的变化,这也是state唯一的作用。 state一般和事件一起使用,我们先看state,然后看看state和事件怎样结合。 这是一个简单的开关组件,开关状态会以文字的形式表现在按钮的文本上。 首先看render方法,返回了一个button元素,给button注册了一个事件用来处理点击事件,在点击事件中对state的on字段取反,并执行 this.setState() 方法设置on字段的新值。一个开关组件就完成了。 组件渲染完成后,必须有UI事件的支持才能正常工作。 React通过将事件处理器绑定到组件上来处理事件。 React事件本质上和原生JS一样,鼠标事件用来处理点击操作,表单事件用于表单元素变化等,Rreact事件的命名、行为和原生JS差不多,不一样的地方是React事件名区分大小写。 比如这段代码中,Article组件的section节点注册了一个onClick事件,点击后弹出alert。 有时候,事件的处理器需要由组件的使用者来提供,这时可以通过props将事件处理器传进来。 这个是刚才那个Article组件的使用者,它提供给Article组件的props中包含了一个onClick属性,这个onClick指向这个组件自身的一个事件处理器,这样就实现了在组件外部处理事件回调。 这是一个React组件实现组件可交互所需的流程,render()输出虚拟DOM,虚拟DOM转为DOM,再在DOM上注册事件,事件触发setState()修改数据,在每次调用setState方法时,React会自动执行render方法来更新虚拟DOM,如果组件已经被渲染,那么还会更新到DOM中去。 这些是React目前支持的事件列表。 React的组件拥有一套清晰完整而且非常容易理解的生命周期机制,大体可以分为三个过程:初始化、更新和销毁,在组件生命周期中,随着组件的props或者state发生改变,它的虚拟DOM和DOM表现也将有相应的变化。 首先是初始化过程,这里会着重讲,需要充分理解。 组件类在声明时,会先调用 getDefaultProps() 方法来获取默认props值,这个方法会且只会在声明组件类时调用一次,这一点需要注意,它返回的默认props由所有实例共享。 在组件被实例化之前,会先调用一次实例方法 getInitialState() 方法,用于获取这个组件的初始state。 实例化之后就是渲染,componentWillMount方法会在生成虚拟DOM之前被调用,你可以在这里对组件的渲染做一些准备工作,比如计算目标容器尺寸然后修改组件自身的尺寸以适应目标容器等等。 接下来就是渲染工作,在这里你会创建一个虚拟DOM用来表示组件的结构。对于一个组件来说,render 是唯一一个必须的方法。render方法需要满足这几点:
腾讯Bugly简介Bugly是腾讯内部产品质量监控平台的外发版本,其主要功能是App发布以后,对用户侧发生的Crash以及卡顿现象进行监控并上报,让开发同学可以第一时间了解到App的质量情况,及时机型修改。目前腾讯内部所有的产品,均在使用其进行线上产品的崩溃监控。 |
|