首页 专题 H5案例 前端导航 UI框架

React入门教程

作者:TG 日期: 2016-06-16 阅读: 957
一、简介
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。
ReactJS官网地址:http://facebook.github.io/react/

二、基础模板

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>react</title> <script src="react/react.js"></script> <script src="react/react-dom.js"></script> <script src="react/browser.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> 

  /*your code*/

</script> </body> </html>


在上面的代码中,只有一个特殊点,那就是最后一个 <script> 标签的 type 属性为 text/babel。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel",通过Babel转换成在浏览器中真正执行的内容。

其次,在这里,我们一共用了三个库: react.js 、react-dom.js 和 browser.js ,它们必须首先加载。其中,react.js 是 React 的核心库,react-dom.js 是提供与 DOM 操作相关的功能,browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。

三、ReactDOM.render()
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
如下:将一个 h1 标题,插入 example 节点

<script type="text/babel"> ReactDOM.render( 

  <h1>Hellow World!</h1>, 

  document.getElementById("example") 

 ); </script>



注意:render里面第二个参数必须使用JavaScript原生的getElementByID方法。

四、JSX语法

HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。
我们来看一个例子:

<script type="text/babel">

   var names=['Alice','Emily','Kate'];   

   ReactDOM.render(   

     <div>   

     {   

        names.map(function(name){   

          return <div>Hello {name}</div>   

        })   

     }   

     </div>,   

     document.getElementById("example")   

   );

</script>

输出:

上面的代码和输出结果, 充分体现了JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。

到这里,我们知道JSX 允许直接在模板插入 JavaScript 变量。但是,当JavaScript变量是一个数组时,会怎样呢?

var arr=[   

<h1>Hello World</h1>,   

<h2>React</h2>   

];

ReactDOM.render(   

  <div>{arr}</div>,   

  document.getElementById("example")   

);

输出:

从输出结果来看, JSX 会把数组的所有成员,添加到模板里。

可以去 JSX 语法 里学习更多 JSX 相关的知识

到这里,我相信你对React已经有了初步的了解,接下来,我们要学习如何用React去构建组件。

五、组件

所谓组件,即封装起来的具有独立功能的UI部件。React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义成组件,然后将小的组件通过组合或者嵌套的方式构成大的组件,最终完成整体UI的构建。例如,Facebook的instagram.com整站都采用了React来开发,整个页面就是一个大的组件,其中包含了嵌套的大量其它组件。

一个优秀的组件,应该具备哪些特征呢? 在React看来:
(1)可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件

(2)可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;
(3)可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;

5.1 构建组件

在React中,React.createClass 方法就用于生成一个组件类。

var HelloMessage=React.createClass({   

  render:function(){   

    return <h1>Hello {this.props.name}</h1>   

  }   

});   

ReactDOM.render(   

  <HelloMessage name="Dennis"/>,   

  document.getElementById('example')   

);

输出:

上面的代码中,变量HelloMessage就是一个组件类。我们在模板中插入<HelloMessage />时,会自动生成HelloMessage的一个实例。
注意事项:
(1) 所有组件类都必须有自己的render方法,用于输出组件。
(2) 组件类的第一个字母必须大写。
(3) 组件类只能包含一个顶层标签。比如(<h1></h1><p></p>,这是错误的。 )

相信你也注意到了,在插入<HelloMessage />时,我们给了它一个name,也就是属性。
在创建组件时,我们可以像原生的HTML标签一样,可以加入任意属性,不过,要注意的是,添加class属性时,要写成className;添加for属性时,要写成htmlFor。这是因为class和for是JavaScript的保留字。

组件的style属性的设置方式也值得注意,要写成style={{width: this.props.witdh}}

var HelloMessage=React.createClass({   

  render:function(){   

    return <h1 style={{color:this.props.color}}>Hello {this.props.name}</h1>   

  }   

});   

ReactDOM.render(   

  <HelloMessage name="Dennis" color="red"/>,   

  document.getElementById('example')   

);


5.2 this.props对象

能设置属性,我们当然也能获取属性。
在React里,组件的属性可以在组件类的this.props对象上获取,就如上面的代码一样,要获取name属性,就通过this.props.name读取。

this.props 对象的属性与组件的属性一一对应,但是,有一个例外,就是 this.props.children 属性。它表示组件的所有子节点

var NotesList=React.createClass({   

  render:function(){   

    return (   

      <ul>   

      {   

         React.Children.map(this.props.children,function(child){   

           return <li>{child}</li>;   

         })   

      }   

      </ul>   

    );   

 }   

});   

ReactDOM.render(   

  <NotesList>   

    <span>Hello</span>   

    <span>World</span>   

  </NotesList>,   

  document.body   

);

输出:



在上面的代码中,NotesList组件有两个span子节点,它们都可以通过this.props.children获取。


注意:this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。


不过,React为我们提供了React.Children工具方法来处理this.props.children。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。更多的 React.Children 的方法,请参考官方文档。


5.3 获取真实的DOM节点


在React里,其引入了虚拟DOM(Virtual DOM)的机制。所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。


有时,我们需要从组件内获取真实的DOM节点,这时就要用到 ref 属性。

var MyFrom=React.createClass({   

  handleClick:function(){   

    console.log(this.refs.tel.value); 

  },   

  render:function(){   

    return(   

      <div>   

        <input type="text" ref="tel"/>   

        <input type="button" value="获取电话" onClick={this.handleClick}/>   

      </div>   

    );   

  }   

});   

ReactDOM.render(   

  <MyFrom/>,   

  document.getElementById("example6")   

);

输出:



上面代码中,我们需要点击按钮来获取文本输入框的值。这时,由于虚拟 DOM 是拿不到用户输入的,所以我们就必须获取真实的 DOM 节点。而在React里,我们是通过给DOM添加 ref 属性,然后在组件类中,使用this.refs.[refName] ,就会返回这个真实的 DOM 节点。  

需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。  

React 组件支持很多事件,除了 Click 事件以外,还有 KeyDown 、Copy、Scroll 等,完整的事件清单请查看官方文档


5.4  this.state

React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。   

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。


var LikeButton = React.createClass({   

  getInitialState: function() {   

    return {liked: false};   

  },   

  handleClick: function(event) {   

    this.setState({liked: !this.state.liked});   

  },   

  render: function() {   

    var text = this.state.liked ? 'like' : 'haven\'t liked';   

    return (   

      <p onClick={this.handleClick}>   

      You {text} this. Click to toggle.   

      </p>   

    );   

  }   

});


上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。  

由于 this.props 和 this.state 都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。


5.5 表单


诸如 <input>、<textarea>、<option> 这样的表单组件不同于其他组件,因为他们可以通过用户交互发生变化。这些组件提供的界面使响应用户交互的表单数据处理更加容易。

var Input = React.createClass({   

  getInitialState: function() {   

    return {value: 'Hello!'};   

  },   

  handleChange: function(event) {   

    this.setState({value: event.target.value});   

  },   

  render: function () {   

    var value = this.state.value;   

    return (   

      <div>   

         <input type="text" value={value} onChange={this.handleChange} />   

         <p>{value}</p>   

      </div>   

    );   

  }  

});   

ReactDOM.render(<Input/>, document.body);

上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况,更多介绍请参考官方文档





关注”全栈技术杂货铺“

全栈技术杂货铺