美文网首页
与jQuery对比来初探React

与jQuery对比来初探React

作者: RichardBillion | 来源:发表于2016-04-24 01:05 被阅读4168次

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

    要求:

    • 没有文字输入,tweet按钮不可点击;未添加图片时图片按钮显示Add Photo,添加图片后显示Photo Added。
    • 另外,只要添加了图片,tweet按钮就可以点击,即使未输入文字。
    • 一张图片相当于23个文字的长度,这儿仅用toggle来模拟添加图片就好;
    • 超出文字部分高亮显示(在这儿,我们把多余字符拿到textarea外面高亮了,简单一些);
    效果图是这个样子滴 (关于丑陋的样式大家就先别计较了)

    先来用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,从而改变展示。

    • 简单 :只要表达出这个程序在该段时间应该长什么样,当底层数据变化时,React会自动处理所有界面的更新。
    • 声明式:数据变化后,会自动刷新,但只更新变化的部分。

    特性:

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

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

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

    预渲染特性——Pre-rendering

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

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

    相关文章

      网友评论

          本文标题:与jQuery对比来初探React

          本文链接:https://www.haomeiwen.com/subject/jjztrttx.html