与jQuery对比来初探React

2016-04-24  本文已影响4168人  RichardBillion

任务:利用React编写一个Tweet Box。

要求:

效果图是这个样子滴 (关于丑陋的样式大家就先别计较了)

先来用jquery实现一下

  <!DOCTYPE html>
<html>
<head>
    <title>
    </title>
    <script src="jquery.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <meta charset="utf-8">

</head>
<body>
<div class="container"> 
    <div class="well clearfix">
        <div class="alert alert-warning hidden ">
        <strong>Oops! Too Long:</strong> ...<span class="beforeOverflow"></span><strong class="bg-danger" ></strong>
        </div>
        <textarea class="form-control"></textarea>
        <button class="btn btn-default pull-right tweet">Tweet</button>
        <button class="btn btn-default pull-right photo">Add Photo</button>
        <span class="pull-right">140</span>
    </div>
</div>
<script type="text/javascript">
    $(function(){
        var tweet=$('.tweet'),
            textVal=$('textarea'),
            photo=$('.photo'),
            len=0,
            characters=$('span');
        tweet.prop("disabled",true);
        textVal.on("input",function(e){
            len=$(this).val().length;
            if(len){
                tweet.prop('disabled',false);
            }else{
                tweet.prop('disabled',true);
            }   
            if(photo.hasClass('isOn')){
                characters.text(140-23-len);
            }else{
                characters.text(140-len);
            }
            remainingCharaters();
        });
        photo.on("click",function(e){
            if(photo.hasClass('isOn')){
                photo.removeClass('isOn').text('Add Photo');
                characters.text(140-len);
                if(len==0){
                    tweet.prop('disabled',true);
                }
            }else{
                photo.addClass('isOn').text('Photo Added');
                characters.text(140-23-len);
                if(len==0){
                    tweet.prop('disabled',false);
                }   
            }
            remainingCharaters();
        });
        function remainingCharaters(){
            var num=parseInt(characters.text());
            console.log(num);
            if(num>=0){return;}
            if(photo.hasClass('isOn')){
                $('.beforeOverflow').text(textVal.val().substring(130-23,140-23));
                $('.bg-danger').text(textVal.val().substring(140-23));
            }else{
                $('.beforeOverflow').text(textVal.val().substring(130,140));
                $('.bg-danger').text(textVal.val().substring(140));
            }       
            $('.alert.alert-warning').removeClass('hidden');
        }
    })
</script>
</body>
</html>

从以上代码中大家可以看出,tweet按钮的点击与字数超出后的警示都是和剩余字数相关的,而剩余字数又和textarea和add photo按钮有关,因此这两个事件严重耦合在一起,每次为实现需求做条件判断时,几乎每次都要把另外一个事件对剩余字数的影响考虑进来。这个功能还算是比较简单的,如果耦合的事件再多一些,那么我们在每一个事件发生时,都要做很多判断,然后再去操作对应的DOM,这真的是个体力活儿。

而 react,在这方面就做的比较让人省心了,它仅仅需要我们去关注当前的状态。它就像是一个有限状态机,我们只需对于不同状态去设置相应的表现就好,而不用像jquery那样时时刻刻去记着其它事件带来的影响。
下面是react的实现:

<!DOCTYPE html>
<html>
<head>
    <script src="jquery.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script src="./react-demos-master/build/react.js"></script>
    <script src="./react-demos-master/build/react-dom.js"></script>
    <script src="./react-demos-master/build/browser.min.js"></script>
    <meta charset="utf-8">
    <title>JS Bin</title>
</head>
<body>
    <div id="example"></div>    

<script type="text/babel">
var TweetBox = React.createClass({
    getInitialState:function(){
        return{
            text:"",
      photoAdded:false
        }
    },
    handleChange:function(e){
        this.setState({
            text:e.target.value
        })      
    },
  remainingCharacters:function(e){
    if(this.state.photoAdded){
      return 140-23-this.state.text.length;
    }else{
      return 140-this.state.text.length;
    }
  },
  togglePhoto:function(e){
    this.setState({
      photoAdded:!this.state.photoAdded
    })
  },
  overflowText:function(e){
    if(this.remainingCharacters()>=0){return;}
    var beforeOverflowText,afterOverflowText;
    if(this.state.photoAdded){
        beforeOverflowText=this.state.text.substring(140-23-10,140-23),
        afterOverflowText=this.state.text.substring(140-23);
    }else{
        beforeOverflowText=this.state.text.substring(140-10,140),
        afterOverflowText=this.state.text.substring(140);
    }    
        return  (
          <div className="alert alert-warning">
          <strong>Oops! Too Long:</strong> ...{beforeOverflowText}<strong className="bg-danger" >{afterOverflowText}</strong>
          </div>
          );
  },
  render: function() {
        return (
         < div className = "well clearfix" >
          {this.overflowText()}
          < textarea className = "form-control" onChange={this.handleChange}> < /textarea>
          <br/ >
          < button className = "btn btn-primary pull-right" disabled={this.remainingCharacters()===140} > Tweet < /button> 
          <button className="pull-right btn btn-primary" onClick={this.togglePhoto}> {this.state.photoAdded?"Photo Added":"Add Photo"}</button>
          <span className="pull-right">{this.remainingCharacters()}</span>
        </div > );
  }
    
});
ReactDOM.render( < TweetBox / > , document.getElementById("example"));
</script>
</body>
</html>

本案例摘抄自:http://www.th7.cn/web/js/201508/118318.shtml ,这里对两种做了详细的分析对比,值得一看。

为什么使用React?

虽然在这个例子中,是用react在代码量上对比jquery没有看出优势,但是要记得,react可是为不断扩大的项目而生的。对于逻辑复杂的组件来说使用react是相当方便的,因为在这个过程中我们只用去考虑组件当前的状态和可能的改变,而不是像jquery去不断的操作DOM,不断去判断各种情况,然后在几个方法之间来回穿梭。react的逻辑很符合我们对现实世界的认知,状态改变之后,会自动的去render,从而改变展示。

特性:

虚拟DOM机制,每当数据变化,React会重新构建整个DOM树,将当前DOM树和上一次的作比较,这一过程都通过虚拟DOM进行,最后将需要变化的部分进行实际渲染更新。

组件化【React对你的唯一要求】:

和MVC思想的框架不同,每个组件独立封装,功能独立,我们只需关心自己部分的逻辑。与单一功能原则相同:独立的组件应该只做一件事情。

预渲染特性——Pre-rendering

虚拟DOM不依赖浏览器,可以在任何javascript环境执行。所以在后端运行代码也能渲染整个DOM,生成HTML字符串,返回给浏览器。这样,页面SEO和首次打开速度都可以解决。

rails项目中只要使用react-rails gem 就可以在rails后端渲染前端React组件。

上一篇下一篇

猜你喜欢

热点阅读