React入门及资源指引
因为工作需要,这段时间一直在看React相关的东西,不得不感叹Facebook在开源项目和软件架构方面的实力,其在React中提出的一些设计思想非常新颖,极大的简化了前端开发的代码逻辑。本文将介绍React相关的基础知识,以及本人在学习过程发现的好的学习资料。 React简介什么是ReactReact是Facebook开源的一套用来创建用户界面的JS库,它重在界面渲染,因此很多人认为React是传统MVC中的V(视图),使用React你可以轻松构建可交互、基于状态的、可复用的UI组件。 Facebook创建React的初衷是想使得构建随着时间流逝数据不断变化的大规模应用程序变得简单,Facebook工程师认为传统的MVC模式已经不适用于构建这种大规模应用,因为当系统中的模型和对应的视图越来越多时,其复杂程度就会迅速扩大,加之可能存在的双向数据流动,导致程序难以理解和调试。 React有两个主要思想:
为什么使用React选择React无非是看中了它所表现出的突出优点:
当然React也不是完美的,它的JSX语法虽然提供了强大的功能,但它却将HTML结构分散进了JS文件中,不利于初学者对网页整体结构的把握,同时Css-in-js的写法也背离了Web标准倡导的表现结构逻辑分离的思想。如何取舍还要看实际情况。 快速开始React学习想要快速开始学习React,官方tutorial是个不错的选择,上面包含了构建React组件的关键性内容。如果你想亲手敲两行代码体验一下,你可以下载一个starter kit,里面包含了相关依赖文件和一些实例,当然你也可以使用jsfiddle在线体验。 JSXJSX是React提供的用来快速创建React树节点的语法糖,它能够使用类似HTML的语法创建JavaScript对象,当然你也可以使用提供的api手动创建。 例如我们事先创建了一个Nav组件,那么在对应的Dom节点渲染它时就可以像下面一样: var navElement = <Nav className='nav' />; //jsx语法,react会自动将其转换成javascript 对象 ReactDOM.render(navElement,/*真实dom节点*/); //渲染 JavaScript 表达式JSX语法的一个重要特点是能够使用JavaScript表达式,通过在属性值或子组件混入js表达式,能够轻易的写出更加复杂的组件,js表达式需要用一对大括号{}包裹起来。 例如属性值混入js表达式: //显示不同的样式类 var person = <Person className={window.isLoggedIn ? 'logged' : null />; //输入框禁止输入 var input = <input type='button' disabled={false} />; 子组件混入js表达式: //根据isLoggedIn的值嵌入不同的子组件 var content = <Container> {window.isLoggedIn ? <Nav /> : <Login />}</Container>; //数组循环创建多个子组件,key属性不能省略,否则会报错 var results = [1,2,3,4]; var list = <ol> {results.map(function(result,index) { return <li key={index}>{result}</li>; })} </ol> JSX语法有几个需要注意的地方:
组件React提倡组件化思想,认为一个应用应该是多个互相独立的组件构成的大组件,每个组件只关心自己部分的逻辑。如下图的评论界面所示,一个评论组件CommentBoxComponent由CommentListComponent和FormBoxComponent组件组成,相应的CommentListComponent组件又由CommentItemComponent和ButtonComponent组成。
组件的划分原则对于初学者而言,想要很好的对UI进行组件划分可能比较困难,但是遵循一些组件划分原则是有益的:
如何创建组件React提供了createClass来创建组件,它接受一个对象作为参数,该对象包含一些属性和函数来具体描述一个组件,其中render函数是必须的,其他的状态初始化函数以及生命周期相关的函数都是可选的: //注意Component首字母大写 var Component = React.createClass({ getIntialState: function(){},//初始化组件状态 getDefaultProps: function(){},//初始化组件的默认属性 propTypes: {},//规定属性的存在性和类型 //一些生命周期相关函数 componentWillMount: function(){},//组件被嵌入之前触发 componentDidMount: function(){},//组件被嵌入之后触发 componentWillReceiveProps: function(){},//当props有改变时触发 componentWillUnmount: function(){},//组件被注销之前触发 //渲染函数,不能省略 render: function() { return <h1>Hello </h1> ; } }); 以上是ES5的写法,如果你看了一些脚手架项目,你会发现有些使用了ES6的语法,ES6创建组件的语法有很大的不同: class Component extends React.Component { constructor() { super(); this.state = { //组件状态 }; } static defaultProps = { //组件属性 }; render() { return ( <div onClick={this.handleClick}> You {text} this. Click to toggle. </div> ); } } 我们可以看到使用了ES6语法的组件构建很像在编写面向对象编程时创建类,更多写法的不同,可以参见es5-es6写法对照表。 区分props和state前面我们有涉及props和state这个两个概念,这里做一下解释。 props当我们在使用定义好的组件时,可以向其添加一些属性,在组件定义的内部,可以通过this.props来访问这些属性,如下在render方法里渲染动态数据: var Component = React.createClass({ getDefaultProps: function(){ return { name: 'world' } },propTypes: { name: React.PropTypes.string //设置属性的类型 },render: function(){ return ( <h1>Hello,{this.props.name}!</h1> //访问name属性 ); } }); ReactDOM.render(<Component name="Handsome" />,document.body); 其中getDefaultProps用来设置默认的属性值,propTypes来设置属性的类型,在使用时如果属性类型不匹配会提示。 this.props是只读的,它通常用来传递来自父组件的数据,也是React构建单向数据流的方式。 state相同的组件之所以能够表现出不一样的UI是因为它们内部拥有不同的状态(states),每个组件都可以拥有自己的state,并且可以在需要的时候通过props传递给子组件。组件可以通过setState函数来修改内部的状态,同时触发界面的渲染。 var ParentComponent = React.createClass({ getInitialState: function(){ return { name: 'Tyler McGinnis',friend: 'Tom' } },handleClick: function(e){ this.setState({name: 'Tim'}); //更改状态 },render: function(){ return ( <div> <h3> Name: {this.state.name} </h3> //点击触发事件,调用handleClick改变组件状态 <button onClick={this.hanleClick}>change name</button> <Component name={this.state.friend} /> //传递状态到子组件 </div> ) } }); 这里需要注意的是getInitialState是用来初始化组件内部状态的默认值,不要在该方法里面使用this.props,除非某个属性有明确的语义是被用来初始化state的,详细请参看这里。 diffrentprops是只读的,不能够在组件内部修改,它是父组件向子组件传递数据的途径;state是组件自身的状态,它不能是父组件传递过来的数据,并且state是可以改变的。 合理的状态操作是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props 传给子组件。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。 生命周期如前面组件创建里提到,组件创建时可以提供几个生命周期函数,这些函数决定了组件在不同的时期进行的操作。
另外React还提供了一个用来优化渲染的周期函数shouldComponentUpdate,它可以用来判断一次状态改变是否需要重新渲染,更多生命周期函数介绍参见这里 事件系统React有内建的跨浏览器的事件系统,你可以在组件里以添加属性的方式绑定事件和相应的处理函数,如上面例子中ParentComponent组件里通过设置onClick属性绑定事件的处理函数handleClick。这种事件绑定方法极大的方便了事件操作,不用再像以前先定位到Dom节点,再通过addEventListener绑定事件,还要用removeEventListener解绑。当组件注销时,react会自动帮我们解绑事件。更多React支持的事件,请参见这里。 进阶如果你是刚刚接触React,那么当你阅读官方的tutorial文档时,会觉得这玩意原来这么简单,无非是将页面功能组件化,调用为数不多的几个api,按照教程一步一步来很快就编写出一个评论应用。当你想利用脚手架快速搭建企业级的React开发环境时,你会也许会用到react-starter-kit,但是他却有点“名不符实”,因为匮乏的文档说明,让其对新手并不友好。相比之下react-redux-universal-hot-example则更加易于理解和学习。值得注意的是学习React,仅仅是学习框架本身是不够,因为当你阅读代码的过程中,你会发现npm是基本的;webpack也是必须的;你还要知道ES6相关语法,相应的你要懂得使用Babel来转换ES5;更进阶你要开始学习全新的程序设计模式Flux和Redux来管理应用的状态等等。学习这些知识不可能一蹴而就,当你遇到某个解不开的点时,不妨先跳过,随着学习的深入,当你回头来看时就会有种恍然大悟的感觉。 资源索引The Only React.js Tutorials and Resources You’ll Need,介绍了很多React学校相关的资源,上面的每篇文章都值得一读。 一看就懂的ReactJs入门教程(精华版) React的一些概念对React的一些概念进行了阐述。 React.js Tutorial Pt 1: A Comprehensive Guide to Building Apps with React.js 非常不错的tutorial,作者思路很清晰,一步步讲解并且附有实例,系列文章还没更新完 React 入门实例教程,阮一峰写的实例教程,里面包含了各个关键知识点的实例代码。 es5-es6语法对比 ,比较详细的react es5-es6语法对照表,看完它对理解一些项目代码比较有用 react style guide,react 代码书写风格的一篇文章,遵守大家都在用的一些规则,对阅读源码很有帮助。 浅谈 React、Flux 与 Redux,对React、Flux、Redux之间的关系进行了很好的阐述。 Full-Stack Redux Tutorial,这篇文章介绍了如何使用Redux构建同构应用,通过一个投票应用,全面介绍了整个开发流程,非常值得阅读。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |