初探react

知道这个框架有一段时间了,可是项目中没有用到,也懒得整理,最近两天比较清闲,又想起了它。好了,废话不多说了,都是干货。

  1. react是个什么框架?
  2. 为什么用react?
  3. react 的原理
  4. react有什么特点?
  5. 语法 & 几个小例子
  6. react的一些总结

react是个什么框架?

React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。

很多人认为 React 是 mvc 中的 V(视图),它可以与其他的框架共存;

react 的原理

在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而 复杂或频繁的DOM操作通常是性能瓶颈产生的原因 (如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。React为此引入了 虚拟DOM(Virtual DOM) 的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。

如果你像在90年代那样写过服务器端Render的纯Web页面那么应该知道,服务器端所要做的就是根据数据Render出HTML送到浏览器端。如果这时因为用户的一个点击需要改变某个状态文字,那么也是通过刷新整个页面来完成的。服务器端并不需要知道是哪一小段HTML发生了变化,而只需要根据数据刷新整个页面。换句话说,任何UI的变化都是通过整体刷新来完成的。而React将这种开发模式以高性能的方式带到了前端,每做一点界面的更新,你都可以认为刷新了整个页面。至于如何进行局部更新以保证性能,则是React框架要完成的事情。

借用Facebook介绍React的视频中聊天应用的例子,当一条新的消息过来时,传统开发的思路如上图,你的开发过程需要知道哪条数据过来了,如何将新的DOM结点添加到当前DOM树上;而基于React的开发思路如下图,你永远只需要关心数据整体,两次数据之间的UI如何变化,则完全交给框架去做。可以看到,使用React大大降低了逻辑复杂性,意味着开发难度降低,可能产生Bug的机会也更少。

为什么用react?

react为了解决:随着时间数据不断变化的大规模应用程序。主要采用下面的思想:

  • 简单

仅当表现当某一个时间点的应用程序长什么样子,然而当底层数据发生变化,视图数据自动更新;

  • 声明式

数据变化,只是更新变化的部分(这是react的特别之处,下面会讲到)

react有什么特点?

  • 有虚拟的dom树,每次数据更新会对比更改的数据,只做diff的更新;
  • 事件循环内的两次数据变化会被合并,列如,数据从A改成B,然后从B改成A,react会认为没有发生任何变化;
  • react推荐以组件化的方式去重新思考构建UI,主要考虑组件间的分离 ;

语法 & 几个小例子

好吧,先从最熟悉的hello world

1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <script src="build/react.js"></script>
 5     <script src="build/JSXTransformer.js"></script>
 6   </head>
 7   <body>
 8     <div ></div>
 9     <script type="text/jsx">
10       // ** Our code goes here! **
11     </script>
12   </body>
13 </html>

这边主要引入2个js,分别是react.js 和 JSXTransformer.js,他们需要首先加载,其中JSXTransformer.js是将jsx转换成javascript语法的。这一步很耗时间,实际应用的时候,应该放到服务器上完成。

下面我们看下react的基本方法

React.render是React最基本的方法,是将jsx转换成html ,并且插入到DOM

1 React.render(
2         <h1>Hello, world!</h1>,
3         document.getElementById('container')
4       );

这里需要注意的是,react并不依赖jQuery,当然我们可以使用jQuery,但是render里面第二个参数必须使用JavaScript原生的getElementByID方法,不能使用jQuery来选取DOM节点。

到这里我们已经迈入了React的大门。

下面说下jsx的语法

JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。

一定要使用JSX吗?

这个不一定,你不需要为了 React 使用 JSX,可以直接使用纯粹的 JS。但我们更建议使用 JSX , 因为它能定义简洁且我们熟知的包含属性的树状结构语法。

对于非专职开发者(比如设计师)同样比较熟悉。XML 有固定的标签开启和闭合。这能让复杂的树更易于阅读,优于方法调用和对象字面量的形式。

它没有修改 JavaScript 语义。

再来个稍微复杂些的例子,做个搜索功能

React是基于组件化的开发,那么组件化开发最大的优点是什么?毫无疑问,当然是复用。

搜索

首先搜索肯定是要有个search的文本框&&搜索按钮

var Search = React.createClass({
        render: function() {
          return (
            <div>
               {this.props.searchType}:<input type="text" />
               <button>Search</button>
            </div>
          );
        }
      });

后面根据不同的内容去搜索(title,content)

 1 var Page = React.createClass({
 2         render: function() {
 3           return (
 4             <div>
 5                <h1>Welcome!</h1>
 6                <Search searchType="Title" />
 7                <Search  searchType="Content" />
 8             </div>
 9           );
10         }
11       });

最后render渲染添加到DOM

1 React.render(
2         <Page />,
3         document.getElementById('container')
4       );

注意标红处

1、获取属性的值用的是this.props.属性名

2、创建的组件名称首字母必须大写。

状态切换改变(组件其实是状态机State

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')
      );

我们又使用到了一个方法getInitialState,这个函数在组件初始化的时候执行,必需返回NULL或者一个对象。这里我们可以通过this.state.属性名来访问属性值,这里我们将enable这个值跟input的disabled绑定,当要修改这个属性值时,要使用setState方法。我们声明handleClick方法,来绑定到button上面,实现改变state.enable的值.

1、getInitialState函数必须有返回值,可以是NULL或者一个对象。

2、访问state的方法是this.state.属性名。

3、变量用{}包裹,不需要再加双引号。

4、组件的生命周期

组件的生命周期分成三个状态:

  • 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):组件判断是否重新渲染时调用

react的一些总结

1、ReactJs是基于组件化的开发,所以最终你的页面应该是由若干个小组件组成的大组件。

2、可以通过属性,将值传递到组件内部,同理也可以通过属性将内部的结果传递到父级组件(留给大家研究);要对某些值的变化做DOM操作的,要把这些值放到state中。

3、为组件添加外部css样式时,类名应该写成className而不是class;添加内部样式时,应该是opacity:{this.state.opacity};"。

4、组件名称首字母必须大写。

5、变量名用{}包裹,且不能加双引号。

参考文档:http://www.tuicool.com/articles/ii6Nn2