React简单介绍
React背景知识
React是一个用于构建用户界面的JavaScript库,主要用于构建UI,而不是一个MVC框架,但可以使用React作为MVC架构的View层轻易的在已有项目中使用,它是一个用于构建用户界面的JavaScript库,起源于Facebook的内部项目,用来架设Instagram的网站,于2013年5月开源。React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
以前没有ajax技术的时候,web页面从服务端整体渲染出html输出到浏览器端进行渲染,同样的,用户的一个改变页面的操作也会刷新整个页面来完成。直到有了ajax出现,实现页面局部刷新,带来的高效和分离让web开发者们惊叹不已。但随之而来的问题是,复杂的用户交互及展现需要通过大量的DOM操作来完成,这让页面的性能以及开发的效率又出现了新的瓶颈。
时至今日,谈到前端性能优化,减少DOM元素、减少reflow和repaint、编码过程中尽量减少DOM的查询等手段是大家耳熟能详的。而页面任何UI的变化都是通过整体刷新来完成的。幸运的是,React通过自己实现的DOMDiff算法,计算出虚拟页面当前版本和新版本之间的差异,最小化重绘,避免不必要的DOM操作,解决了这两个公认的前端性能瓶颈,实现高效DOM渲染。
我们知道,频繁的操作DOM所带来的性能消耗是很大的,而React之所以快,是因为它不直接操作DOM,而是引进虚拟DOM的实现来解决这个问题
对于页面的更新,React通过自己实现的DOMDiff算法来进行差异对比、差异更新,反映到页面上就是只重绘了更新的部分,从而提高渲染效率。
备注:以下性能阐述参考自尤雨溪。
对于React的性能方面,想啰嗦几句:
1.React从来没有说过“React比原生操作DOM快”。React的基本思维模式是每次有变动就整个重新渲染整个应用。如果没有VirtualDOM,简单来讲就是直接重置innerHTML。
2.在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。
3.不要天真地以为VirtualDOM就是快,diff不是免费的,VirtualDOM真正的价值从来都不是性能,而是它
1)为函数式的UI编程方式打开了大门;
2)可以渲染到DOM以外的其他场景,如backend、native。
组件化
在业务开发中,遇到公共的模板部分,我们不得不将模板和规定的数据格式耦合在一起来实现组件。而在React中,我们可以使用JSX语法来封装组件,将组件的结构、数据逻辑甚至样式都聚合在一起,更加简单、明了、直观的定义组件。
有了组件化的实现,我们可以很直观的将一个复杂的页面分割成若干个独立组件,再将这些独立组件组合完成一个复杂的页面。这样既减少了逻辑复杂度,又实现了代码的重用。
React基础
模板
Hello,博看文思!
, document.getElementById(‘example') );JSX
上一节的代码,HTML语言直接写在JavaScript语言之中,不加任何引号,这就是JSX的语法,它允许HTML与JavaScript的混写
JSX的好处:
1.使用JSX语法来封装组件有什么好处:
1)熟悉的代码
2)更加语义化
3)更加抽象且直观
2.几个注意点:
1)render的方法中return的顶级元素只能是一个;
2)如果要定义样式的时候,不能这样去写
//不要出现类似的错误,style=“opacity:{this.state.opacity};”
3)使用className和htmlFor来替代对应的class和for
提示:关于组件化的话题,感兴趣的话可以继续关注Vuejs、Webcomponents等对组件的写法。/**随着更为复杂的多端环境的出现,组件标准化还有着更大的想象空间,React的组件定义不是终点,也不一定是标准,但会在组件化的道路上留下深刻de影响。**/
JSX基本语法:
varnames=[‘Alice',‘Emily',‘Kate']; ReactDOM.render({ names.map(function(name,key){ return}) }Hello,{name}!
上面代码体现了JSX的基本语法规则:遇到HTML标签(以<开头),就用HTML规则解析;遇到代码块(以{开头),就用JavaScript规则解析。
JSX允许直接在模板插入JavaScript变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
vararr=[Helloworld!
,Reactisawesome
, ]; ReactDOM.render({arr}, document.getElementById(‘example') );
组件
1.概念
React允许将代码封装成组件(component),然后像插入普通HTML标签一样,在网页中插入这个组件。React.createClass方法就用于生成一个组件类
2.代码示例
varHelloMessage=React.createClass({ render:function(){ returnHello{this.props.name}
; } }); ReactDOM.render(, document.getElementById(‘example') ); varHelloMessage=React.createClass({ render:function(){ return Hello{this.props.name}; } }); ReactDOM.render( , document.getElementById(‘example') );
this.props.children
this.props对象的属性与组件的属性一一对应,但是有一个例外,就是this.props.children属性。它表示组件的所有子节点
varNotesList=React.createClass({ render:function(){ return({ /* *因为this.props.children的返回值会根据子节点的数量返回undefined,object,array. *所以react提供了一个react.Children的方法专门处理this.props.children **/ React.Children.map(this.props.children,function(child){ return
); } }); ReactDOM.render(- {child}
; }) }hello world , document.getElementById(“example”) );
PropTypes
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求。
varMyTitle=React.createClass({ propTypes:{ /* *声明title属性是必须的,并且数据类型要为字符串,相当于是规范化的接口文档 **/ title:React.PropTypes.string.isRequired, }, render:function(){ return{this.props.title}
; } }); vardata=“123”; ReactDOM.render(, document.getElementById(“example”) );
错误示范:
vardata=123; ReactDOM.render(, document.body );
getDefaultProps
getDefaultProps方法可以用来设置组件属性的默认值
varMyTitle=React.createClass({ getDefaultProps:function(){ return{ title:”helloworld” } }, render:function(){ return{this.props.title}
; } }); //vardata=“123”; ReactDOM.render(, document.getElementById(“example”) );
获取真实的DOM节点
组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫做虚拟DOM(virtualDOM)。只有当它插入文档以后,才会变成真实的DOM。根据React的设计,所有的DOM变动,都先在虚拟DOM上发生,然后再将实际发生变动的部分,反映在真实DOM上,这种算法叫做DOMdiff,它可以极大提高网页的性能表现。
varMyComponent=React.createClass({ handleClick:function(){ this.refs.myTextInput.focus(); }, render:function(){ return(); } }); ReactDOM.render(, document.getElementById(‘example') );
this.state
组件免不了要与用户互动,React的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染UI。React把组件看成是一个状态机(StateMachines)。通过与用户的交互,实现不同状态,然后渲染UI,让用户界面和数据保持一致。React里,只需更新组件的state,然后根据新的state重新渲染用户界面
varLikeButton=React.createClass({ getInitialState:function(){ /* *设置状态的初始值 **/ return{liked:false}; }, handleClick:function(){ /* *更改状态 **/ this.setState({liked:!this.state.liked}); }, render:function(){ vartext=this.state.liked?‘喜欢':‘不喜欢'; return(你{text}他.点击切换. ); } }); ReactDOM.render( , document.getElementById(‘example') );
由于this.props和this.state都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props表示那些一旦定义,就不再改变的特性,而this.state是会随着用户互动而产生变化的特性。
varInput=React.createClass({ getInitialState:function(){ return{value:‘Hello!'}; }, handleChange:function(event){ this.setState({value:event.target.value}); }, render:function(){ varvalue=this.state.value; return(); } }); ReactDOM.render(,document.body);{value}
组件API
组件的7个方法:
设置状态:setState;
替换状态:replaceState;
设置属性setProps;
替换属性replaceProps;
强制更新:forceUpdate;
获取DOM节点:getDOMNode;
判断组件挂载状态:isMounted。
组件生命周期
初始化
getDefaultProps:设置默认性的值
getInitialState:设置初始的状态
componentWillMount:(组件即将被装载)
render(渲染)
componentDidMount:组件已经被装载,只会在第一个组件被调用的时候出发
运行中
componentWillReceiveProps在组件将要接收到属性的时候,接收属性前
shouldComponentUpdate在接收到新的props或者state,将要渲染之前调用。该方法在初始化渲染的时候不会调用
componentWillUpdate render触发之前,更新
render渲染
componentWillUnmount 在组件从DOM中移除的时候立刻被调用
销毁
componentWillUnmount在组件从DOM中移除的时候被立刻调用
varHello=React.createClass({ getInitialState:function(){ return{ opacity:1.0 }; }, componentDidMount:function(){ this.timer=setInterval(function(){ varopacity=this.state.opacity; opacity-=.05; if(opacity<0.1){ opacity=1.0; } this.setState({ opacity:opacity }); }.bind(this),100); }, render:function(){ return(Hello{this.props.name}