React入门与实践

前言

在腾讯应用宝前端分享会上分享了react,现将资料整理成这篇文章,希望对react的初学者能够有所帮助;如果文中有描述不恰当或者错误的地方,请望斧正。

1. 为什么使用react

react 是facebook在2013年开源的一个javascript库,主要用来快速的构建页面,使用react主要有以下两个原因:

  • 简单的响应式更新。在传统的javascript中,当页面的数据发生变化的时候,我们除了要关注数据的变化,还要更新对应的dom结构,比如一个页面的简单的一个标题This is a title,当其中的内容改为hello world的时候,我们需要如下的操作:
    <h1>This is a title</h1>
    <script>
    var data="hello world";//在实际中是从后台获取数据
    var h1=document.querySelector("h1");
    h1.innerHTML=data;//关注dom结构的变化
    </script>
    如果使用react 的话,只需要将数据设置进去,不需要关注dom结构的变化。
  • 组件化。在react中,我们看到的每一个页面其实都是由一个个组件:header,content,footer等组成,这样可以快速的构建页面,而且还利于组件的复用。

2. react基础

2.1 概览

学习编程语言C++,java可能都是hello world说起的,先看一个简单的hello world的例子:

<!-- javacript files-->
    <script src="lib/react.js"></script>
    <script src="lib/react-dom.js"></script>
    <script src="lib/browser.min.js"></script>
    //...
    <div id="app"></div>
    <script type="text/babel">
        var HelloWorld = React.createClass({
        render: function() {
        return <h2>Hello World</h2>
        }
    })
      const app =document.getElementById("app");
    ReactDOM.render(<HelloWorld  />, app);
    </script>

在上面的代码中,我们看到引入了两个库:react.js,react-dom.js,其实使用react的核心库,在0.14版本之前是一个文件,之后分成了两个,react.js包括了组件相关定义的属性、方法,如:react.createClass,react.Componet等;react-dom.js主要是包括了将一个react组件渲染到页面成为真实dom的相关属性,例如:reactDOM.render,findDOMNode。使用react构建一个组件分为以下两步:
(1)定义一个组件,并给组件一个名称;
(2)使用reactDOM.render()方法将组件渲染到页面上。

2.2 组件定义的两种方式

上面有提到组件,那么react怎么定义一个组件呢。有两种方式定义:React.createClass()与class的方式。

React.createClass

这是是react最早的版本提出的一个创建方式,使用的方式是在rener中返回我们需要在页面上看到的dom结构,代码如上图的helloworld例子所示。

class

第二种方式是使用class的方式,这可能是跟es6相契合吧,一个比较建议使用这样的方式;大体语法是 class componentName extends React.Component(完整代码见附件demo01中的helloworld.html)。

class HelloWorld extends React.Component {
            render(){
                return (
                <h2>Hello World!</h2>
                );
            }
        }

2.3 state vs props

在组件定义后,其组件的数据是我们关注的焦点。react中定义了两个属性来描述组件的数据props与state;我们可以将一个组件想象成一个函数,其中props就是传递的参数并且不可以在函数内修改;而state就是其中定义的变量,我们可以对其中的变量进行维护。

export default class Article extends React.Component {
  render() {
    const { title } = this.props;
    return (
      <div >
        <h4>{title}</h4>
   //...
      </div>
    );
  }
}
<Article  title={title}/>

  

我们只需要传递标题的值就可以了,不需要进行其他的操作,因此使用props。

  constructor() {
    super();
    this.state = {
      title: "Welcome",

    };
  }
<Header changeTitle={this.changeTitle.bind(this)} title={this.state.title} />

  

这个里面的标题是获取input输入框的值,因此设置为state。演示的效果如下:

我们可能提出疑问,就是如果我们将一个函数B嵌入到另一个函数A中,在A中设置一个变量(state),那么B中就可以使用参数(props)的形式了,的确是可行的,这是两种不同的组件:smart component,dumb component.可以参考Dan的文章 Presentational and Container Components

2.4 react中的交互

react中实现事件绑定的方式是非常简单的,只需要在对应的标签中使用驼峰命名法给其一个绑定的函数即可。最常见的就是一个输入框,我们需要获取其值,因此可以给onChange绑定一个事件。其步骤如下:

  1. 定义一个handleChange函数
  2. 在对应的input 中加入函数的绑定input onChange=handleChange(详细代码参见react-webpack)
    export default class Header extends React.Component {
    handleChange(e) {
    const title = e.target.value;
    this.props.changeTitle(title);
    }
    render() {
        <input value={this.props.title} onChange={this.handleChange.bind(this)} />   
    }
    }
      

2.5 生命周期

一个react组件有三种状态:mounting,updating,unmounting
mounting:React Component被render解析生成对应的dom节点并被插入浏览器的DOM结构的过程。
updating:当一个组件的状态state发生变化的时候,会进行重新的render过程。
unmounting:是指一个mounted的React Component对应的DOM节点被从DOM节点移除的过程。

 

 

其每一个生命状态都有封装对应的hook函数,我们可以通过状态的变化过程来进行数据的加载、修改、移除等。以实现页面的初始化和页面数据的更新。以mouting状态为例,在组件渲染之前,我们可以使用getInitalState来指定数据的初始化值,使用componentDidMount来进行ajax请求,从服务器加载数据等操。代码示例可以参照react-webpack/src/components/Content.js

3. react-router

当页面是组件构成的什么,就天然的时候做单页面应用,可以在发生某种情况下替换掉组件就可以呈现不同的内容了。在讲react-router使用之前,让我们先看看路由实现的一个大体的原理。
一个url一般由这几个部分组成:协议、域名、端口、文件路径、文件名、查询条件与hash值,hash值的变化不会使页面进行更新,基于此原理,可以实现页面路由,其过程一般如下:

  • 获取hash的取值情况
  • 给每种hash值注册一个回调函数
  • 利用window.haschange()来监听hash值得变化,并执行相应的回调函数,实现页面的路由。(代码来自http://web.jobbole.com/86407/)
function Router() {
  this.routes = {};
  this.currentUrl = '';
}
Router.prototype.route = function(path, callback) {
  this.routes[path] = callback || function(){};
};
Router.prototype.refresh = function() {
  this.currentUrl = location.hash.slice(1) || '/';
  this.routes[this.currentUrl]();
};
Router.prototype.init = function() {
  window.addEventListener('load', this.refresh.bind(this), false);
  window.addEventListener('hashchange', this.refresh.bind(this), false);
}
window.Router = new Router();
window.Router.init();

在html 5标准出现之前history对象的属性与方法比较简单,一般是使用history.back(),history.forward()实现页面的前进与后退。但是在html5中为其添加了新的方法与和一个事件,使其为我们实现页面路由提供了新的方法。其中常用的方法有: history.pushState向当前浏览器的历史堆栈中添加一个新的url; window.onpopstate会在浏览器进行前进后退的时候进行触发。
react-router对两种方式都有实现,我们可以选择任意一种。其调用方式如下:

   <nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
            <ul  className='main-menu'>
                  <li><Link to="/">首页</Link></li>
            //...       
            </ul>
   </nav>
   <Router history={browserHistory}>
        <Route path="/" component={Layout}>
            <IndexRoute component={Content}></IndexRoute>
          //...
        </Route>
  </Router>

  

posted @ 2016-08-22 09:43  珊瑚月  阅读(748)  评论(0编辑  收藏  举报