现在最热门的前端框架有AngularJS、React、Bootstrap等。自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化是它独特之处及优势所在。
一.ReactJS简介
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。由于React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。
ReactJS官网地址:http://facebook.github.io/react/
二.下载ReactJS,编写Hello,world
ReactJs下载非常简单,为了方便大家下载,这里再一次给出下载地址http://facebook.github.io/react/downloads.html,下载完成后,我们看到的是一个压缩包。解压后,我们新建一个html文件,引用react.js和JSXTransformer.js这两个js文件。html模板如下(js路径改成自己的):
<!DOCTYPE html> <html> <head> <script src="react.js"></script> <script src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> // ** Our code goes here! ** </script> </body> </html>
这里大家可能会奇怪,为什么script的type是text/jsx,这是因为React 独有的JSX语法,跟JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/jsx" 。其次,React 提供两个库:react.js和JSXTransformer.js ,它们必须首先加载。其中,JSXTransformer.js 的作用是将 JSX 语法转为 JavaScript 语法。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
到这里我们就可以开始编写代码了,首先我们先来认识一下ReactJs里面的React.render方法:React.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
下面我们在script标签里面编写代码,来输出Hello,world,代码如下:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> React.render( <h1>Hello, world!</h1>, document.getElementById('container') ); </script> </body> </html>
这里需要注意的是,react并不依赖jQuery,当然我们可以使用jQuery,但是render里面第二个参数必须使用JavaScript原生的getElementByID方法,不能使用jQuery来选取DOM节点。
然后,在浏览器打开这个页面,就可以看到浏览器显示一个大大的Hello,world,因为我们用了<h1>标签。
三.Jsx语法
HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写,了解过AngularJs的看到下面的代码一定会感觉很熟悉的,我们来看代码:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> var names = ['Jack', 'Tom', 'Alice']; React.render( <div> { names.map(function (name) { return <div>Hello, {name}!</div> }) } </div>, document.getElementById('container') ); </script> </body> </html>
这里我们声明了一个names数组,然后遍历在前面加上Hello,输出到DOM中,运行结果如下:
JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员,代码如下:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> var arr = [ <h1>Hello world!</h1>, <h2>React is perfect!</h2>, ]; React.render( <div>*{arr}*</div>, document.getElementById('container') ); </script> </body> </html>
运行结果:
四.ReactJS组件
1.组件属性
ReactJS是基于组件化的开发,下面我们开始来学习ReactJS里面的组件,React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。
下面,我们来编写第一个组件Greet,有一个name属性,然后输出hello + name的值,代码如下:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> var Greet = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; } }); React.render( <Greet name="Jack" />, document.getElementById('container') ); </script> </body> </html>
运行结果:
看到这段代码,接触过AngularJS的朋友们是不是有一种熟悉的感觉,不过这里有几点需要注意:
a.获取属性的值用的是this.props.属性名
b.创建的组件名称首字母必须大写。
c.为元素添加css的class时,要用className.
d.组件的style属性的设置方式也值得注意,要写成style={{width: this.state.witdh}}
2.组件状态
组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI 。下面我们来编写一个小例子,一个文本框和一个button,通过点击button可以改变文本框的编辑状态,禁止编辑和允许编辑。通过这个例子来理解ReactJS的状态机制。先看代码:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> var InputState = React.createClass({ getInitialState: function() { return {enable: false}; }, handleClick: function(event) { this.setState({enable: !this.state.enable}); }, render: function() { return ( <p> <input type="text" disabled={this.state.enable} /> <button onClick={this.handleClick}>Change State</button> </p> ); } }); React.render( <InputState />, document.getElementById('container') ); </script> </body> </html>
运行效果:
这里,我们又使用到了一个方法getInitialState,这个函数在组件初始化的时候执行,必需返回NULL或者一个对象。这里我们可以通过this.state.属性名来访问属性值,这里我们将enable这个值跟input的disabled绑定,当要修改这个属性值时,要使用setState方法。我们声明handleClick方法,来绑定到button上面,实现改变state.enable的值。效果如下:
原理分析:当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。
这里值得注意的几点如下:
a.getInitialState函数必须有返回值,可以是NULL或者一个对象
b.访问state的方法是this.state.属性名
c.变量用{}包裹,不需要再加双引号
3.组件的生命周期
组件的生命周期分成三个状态:
a.Mounting:已插入真实 DOM
b.Updating:正在被重新渲染
c.Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。
a.componentWillMount()
b.componentDidMount()
c.componentWillUpdate(object nextProps, object nextState)
d.componentDidUpdate(object prevProps, object prevState)
e.componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
a.componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
b.shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
下面来看一个例子:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <script type="text/jsx"> var Hello = React.createClass({ getInitialState: function () { return { opacity: 1.0 }; }, componentDidMount: function () { this.timer = setInterval(function () { var opacity = this.state.opacity; opacity -= .05; if (opacity < 0.1) { opacity = 1.0; } this.setState({ opacity: opacity }); }.bind(this), 100); }, render: function () { return ( <div style={{opacity: this.state.opacity}}> Hello {this.props.name} </div> ); } }); React.render( <Hello name="world"/>, document.body ); </script> </body> </html>
运行效果:
上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。
4.组件的嵌套
React是基于组件化的开发,那么组件化开发最大的优点是什么?毫无疑问,当然是复用,下面我们来看看React中到底是如何实现组件的复用的,这里我们还写一个例子来说吧,代码如下:
<!DOCTYPE html> <html > <head> <script src="es5-shim.min.js"></script> <script src="es5-sham.min.js"></script> <script src="console-polyfill.js"></script> <script type="text/javascript" src="react.min.js"></script> <script type="text/javascript" src="JSXTransformer.js"></script> </head> <body> <div id="container"></div> <script type="text/jsx"> var Search = React.createClass({ render: function() { return ( <div> {this.props.searchType}:<input type="text" /> <button>Search</button> </div> ); } }); var Page = React.createClass({ render: function() { return ( <div> <h1>Welcome!</h1> <Search searchType="Title" /> <Search searchType="Content" /> </div> ); } }); React.render( <Page />, document.getElementById('container') ); </script> </body> </html>
这里我们创建了一个Search组件,然后又创建了一个Page组件,然后我们在Page组件中调用Search组件,并且调用了两次,这里我们通过属性searchType传入值,最终显示结果如图:
五.ReactJs小结
1.ReactJs是基于组件化的开发,所以最终你的页面应该是由若干个小组件组成的大组件。
2.可以通过属性,将值传递到组件内部,同理也可以通过属性将内部的结果传递到父级组件(留给大家研究);要对某些值的变化做DOM操作的,要把这些值放到state中。
3.为组件添加外部css样式时,类名应该写成className而不是class;添加内部样式时,应该是style={{opacity: this.state.opacity}}而不是style="opacity:{this.state.opacity};"。
4.组件名称首字母必须大写。
5.变量名用{}包裹,且不能加双引号。
文章来源:http://www.cnblogs.com/Leo_wl/p/4489197.html