本文为学习笔记,适合入门的童鞋,如有错误,请多多指教。
一、react诞生
Web app的性能瓶颈,主要有以下原因。
(1)Web基于DOM,而DOM很慢。浏览器打开网页时,需要解析文档,在内存中生成DOM结构,如果遇到复杂的文档,这个过程是很慢的。可以想象一下,如果网页上有上万个、甚至几十万个形状(不管是图片或CSS),生成DOM需要多久?更不要提与其中某一个形状互动了。
(2)DOM拖慢JavaScript。所有的DOM操作都是同步的,会堵塞浏览器。JavaScript操作DOM时,必须等前一个操作结束,才能执行后一个操作。只要一个操作有卡顿,整个网页就会短暂失去响应。浏览器重绘网页的频率是60FPS(即16毫秒/帧),JavaScript做不到在16毫秒内完成DOM操作,因此产生了跳帧。用户体验上的不流畅、不连贯就源于此。
(3)网页是单线程的。现在的浏览器对于每个网页,只用一个线程处理。所有工作都在这一个线程上完成,包括布局、渲染、JavaScript执行、图像解码等等,怎么可能不慢?
(4)网页没有硬件加速。网页都是由CPU处理的,没用GPU进行图形加速。
这里我们看到了dom的问题,下面来学习下react做了哪些事情,就大概清楚为什么react解决了以上问题。
优势:
组件可复用性和扩展性好,开发效率提高
前后端渲染模板上的统一,客户端和服务器都可渲染
引入虚拟DOM,每个React组件都拥有一个完整的生命周期,对DOM状态的操作都会批量更新,以期尽可能的减少页面重绘,来追求更好的性能
劣势:
框架100k,本身较大,手机页面基本首屏WIFI/4S,3G/6S,可以考虑客户端缓存
据其他业务反映,无其他劣势,好评一片
框架建议:REACT+后台直出+前端SPA,后续考虑Service Worker、或者上传到cdn减少后续加载
二、基础
React 可以在浏览器运行,也可以在服务器运行;
`react.js` 是 React 的核心库
`react-dom.js` 是提供与 DOM 相关的功能
`Browser.js` 的作用是将 JSX 语法转为 JavaScript 语法,此步骤应在服务器完成
监听jsx文件到js自动转化方法:我们都知道react其实是以jsx的方式编码,这就涉及由jsx到js的转化,以下为自动转化方式
npm install -g react-tools
jsx –watch src/ build/
[JSX] (http://facebook.github.io/jsx/) 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。
重点一:组件
ReactDOM.render 是 React 的最基本方法
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(
<HelloMessage name="John" />,
document.getElementById('example')
);
React 允许将代码封装成组件(component),React.createClass 方法就用于生成一个组件类 HelloMessage
。模板插入 <HelloMessage />
时,会自动生成 HelloMessage
的一个实例(下文的”组件”都指组件类的实例)。所有组件类都必须有自己的 render
方法,用于输出组件。
注意:
1、组件类的第一个字母必须大写,否则会报错。HelloMessage
2、组件类只能包含一个顶层标签,否则也会报错。h1
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
从组件获取真实 DOM 的节点,这时就要用到 ref
属性
重点二:生命周期
组件的生命周期分成三个状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will
函数在进入状态之前调用,did
函数在进入状态之后调用,三种状态共计五种处理函数。
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
<应用>
动画类:可以采用componentDidMount,利用定时器不断变化形状或者透明度等形态
ajax:可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState
方法重新渲染 UI
重点三:state
React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。
getInitialState:用于定义初始状态,也就是一个对象
this.state :属性读取
this.setState: 修改状态值,每次修改以后,自动调用 this.render
方法,再次渲染组件
state和props不同:
this.props
表示那些一旦定义,就不再改变的特性,它们从父组件传递过来,“属于”父组件。this.state
是会随着用户互动而产生变化的特性。故表单类渲染也需要用state,this.state 是组件私有的,可以通过调用 this.setState()来改变它。当 state 更新之后,组件就会重新渲染自己。
重点四:react编码过程:
第一步:拆分用户界面为一个组件树
第二步: 利用 React ,创建应用的一个静态版本
第三步:识别出最小的(但是完整的)代表 UI 的 state,分析是否为state 。简单地对每一项数据提出三个问题:
是从父级通过 props 传入的?可能不是 state 。
不会随着时间改变?可能不是 state 。
能根据组件中其它 state 数据或者 props 计算出来?不是 state 。
第四步:确认 state 的生命周期,判断哪个组件会改变或者说拥有这个 state 数据模型。
找出每一个基于那个 state 渲染界面的组件。
找出共同的祖先组件(某个单个的组件,在组件树中位于需要这个 state 的所有组件的上面)。
要么是共同的祖先组件,要么是另外一个在组件树中位于更高层级的组件应该拥有这个 state 。
如果找不出拥有这个 state 数据模型的合适的组件,创建一个新的组件来维护这个 state ,然后添加到组件树中,层级位于所有共同拥有者组件的上面
第五步:添加反向数据流,组件之间经常交互,从父级到子级比较简单,这里说的从子级到父级
相关链接:
中文社区:http://react-china.org/
facebook react官网:http://facebook.github.io/react/