最近重写WAP项目,为了使前端和后端完全分离,需要完全摒弃原始的JSP页面,采用传统的
HTML+CSS+JS(不乏也会涉及部分HTML5,CSS3,
如 Storage, Location等)作为前端基础,
后端仅需提供数据交互API,
也就几乎类似APP + API的交互模式,
这样就能清晰地独立前端和后端项目,独立部署分发。与此同时,前端展现数据将显得力不从心,
没有JSP中丰富的JSTL标签,于是,我们需要一些纯前端的展现,如模板技术,框架技术,
听闻过如AngularJS,但其略显繁重,
在了解到React之后,
决定用其来作为前端主力。
-
React特性
-
相比其他一些JS框架,React更佳精巧,React眼里一切都是组件,让开发人员使用组件化的思想去构建网页。
-
仅仅是UI
通常我们会使用React作为MVC中的
V,React能够很轻松地融入项目中,
并不需要很复杂的技术。
-
虚拟DOM
在HTML中的DOM节点,对于节点的事件处理,UI更新,都需要我们手动监听事件,再在事件中去更新UI或其他操作,
为此React抽象出一层虚拟DOM,
使得节点事件处理和UI更新更佳轻松,而且性能更佳。
-
数据流
React实现了单向数据流,以减少模板的使用,因此比传统的数据绑定更简单。
-
React几个重要概念
-
组件(Component)
-
在React中,都以组件为最小单元,比如一个简单的组件:
-
上面的代码就是一个简单的React组件,采用JSX语法进行编写,
既然有了组件,我们需要将组件渲染到页面当中(即挂载到某个真实DOM节点):
-
组件状态(State)
-
React中的每个组件都有自己的状态,即一个Object对象。
可以通过this.state.keyName获取状态变量
keyName的值,
通过this.state.setState({keyName: '...'})
设置状态变量keyName的值,这将引起组件被重新渲染(render)。
-
组件规范(Component Specs)
-
render
该方法是必须的。当该方法被调用时,
会检查当前组件的this.props和
this.state,
意味你可以在该方法中开始访问
props和state。
你不应该在该方法中更新当前组件状态(State),这将导致组件重新被render,
因此,render方法应保持清晰干净,仅仅组装各种组件,设置组件属性即可。
-
getInitialState
该方法在组件被挂载前调用,仅调用一次,返回Object作为组件的初始状态,
可通过this.state.keyName访问这些状态变量,
并且可以通过this.state.setState({keyName: '...'})更新组件状态。
-
getDefaultProps
该方法用于返回默认属性,即当父组件没有传入属性值时,将使用这些默认值,
并且这些默认属性将被缓存,即所有该组件的实例共享该这些默认属性。
-
mixins
该属性用于多个组件公用一些方法,但并不推荐,毕竟React提倡的是组件开发,
使用可见这里。
-
statics
顾名思义,statics用于定义组件的静态方法,如
-
displayName
组件名称,可用于调试。
-
一些主要的组件生命周期方法
-
在组件的生命周期中,不同的时间点将对应执行不同的方法。
-
componentWillMount
仅调用一次,在初始化render前被执行,因此,若在该方法中调用
setState,那么render将能看到更新的状态,
并且并不会render只会执行一次,尽管执行了setState。
-
componentDidMount
仅调用一次,在初始化render后被执行,此时,组件已经有对应的真实DOM节点,
因此可以调用React.findDOMNode(this)获取组件的真实DOM节点,
通常会在该方法中去获取数据。
-
componentWillReceiveProps
当组件被赋值新的属性时被调用,可以在该方法中根据新的属性,做一些处理,如
-
shouldComponentUpdate
该方法在render前调用,若返回false,render方法不将被执行,可以在该方法做一些判断,确认是否需要render组件。
-
componentDidUpdate
该方法在当组件更新后且被刷新到DOM节点后被调用,不会在初始化render后调用,
可以在该方法中操作最新的DOM节点。
-
一个简单的例子
-
针对一个简单的登录页面,我们可以将其分为几个组件:
-
我们将上面的页面分为几个比较细粒度的组件为:
可见,即使是简单的input元素,也用Input组件来封装,
也是为了能够进行一些简单的定制化,如样式,事件等。
-
组件通信
-
对于父子级的组件之间,
通过属性传递,回调等就能较好的通信,如
-
而Button组件内部会在onTouchStart时回调其父组件传递的属性onTouch:
-
对于同级别的组件,可以通过其父组件间接通信,即组件1触发事件,调用父组件方法,该方法再调用组件2某方法。
-
状态更新
当一个页面比较复杂时,会由很多组件组装起来,建议对于业务组件,将状态抽象到上层组件中进行统一管理,
也便于页面中的组件能够通信,因为一旦状态更新,就会render,
状态太混乱,造成不必要的UI渲染,或者错误的UI渲染。在业务组件编写中,
可以尽量用props代替不必要的state,
即让组件无状态,将状态更新交由外部组件去控制。
-
组件依赖
React本身并不支持组件依赖管理,
即不能像RequireJs等模块化管理工具一样,能维护模块之间的依赖关系,
比较简单的解决办法是将业务组件都concat到一个文件中,那么组件就能通过组合来调用其他组件。
-
使用webpack管理React组件
React大多第三方组件是遵循npm规范,
即CommonJS规范,
于是我们可以考虑使用webpack来管理React组件的依赖关系,
-
对于React组件管理,webpack可能基本配置就是
-
既然选择了npm规范,因此我们编写的组件也就必须遵循:
-
的确React足够简洁,通过状态来自动进行UI渲染,并且通过diff算法对组件进行最小化DOM操作,使得性能可观,并且轻松进行组件化,
开发出高可复用代码,值得一试。