1

之前对于react的认识只存在与听说,说他有啥virtual DOM,很好的组件化,效率很高之类的,,不过一直没有学习,昨天闲着无聊就开始学习react.发现jsx的写法真是666啊,由于是刚开始学习,所以总的经验不是很多。
我跟着其官网上的教程做了一个评论框的功能,后台用的是node,并没有链接数据库,只是文件流的读写;
最终结果:
clipboard.png

文件结构:

  • react_comment

    • node_modules

    • public

      • build

        • build.js

        • build.js.map

      • js

        • comment.js

        • comment_box.js

        • commemt_form.js

        • comment_list.js

        • entry.js

      • scss

        • comment.scss

    • server

      • server.js

    • comment.json

    • package.json

    • webpack.config.js

webpack.config.js:


    var path = require('path'),
        webpack = require('webpack');
    
    var commonLoaders = [
        {test:/\.js$/,loader:'babel',exclude:'/node_modules/'},    //exclude:不包含这个文件夹下的目录,不然babel也会编译里面的js文件,导致速度变慢
        {test:/\.scss$/,loader:'style!css!autoprefixer!sass'}
    ];
    
    var path = path.resolve(__dirname,'public/build');
    
    module.exports = {
        entry:[
            './public/js/entry.js'        //指定入口文件
        ],
    
        output:{    //指定输出文件路径及name
            path:path,
            filename:'build.js'
        },
        module:{
            loaders:commonLoaders
        },
        resolve:{
            extensions:['','.js','.scss']
        },
        babel:{    //这里我是使用的是babel-loader、babel-preset-2015、babel-preset-react,并没有使用jsx-loader,所以这里作如下配置:
            presets:['es2015','react']
        }
    };

数据源:


    [
        {
            "id": 1388534400000,
            "author": "Pete Hunt",
            "text": "Hey there!"
        }
    ]

入口文件:

import React from 'react';
import ReactDOM from 'react-dom';
import {CommentBox} from './comment_box';
import reset from '../scss/comment';
ReactDOM.render(<CommentBox url='/api/comments' pollInterval={2000} />,document.getElementById('content'));
  1. 这里一定要注意的是渲染组件用的是react-dom,而不是react,所以要把它也require进来

  2. 一定要用原生的document.getElementById()来获取容器

最外层组件


    import React from 'react';
    import $ from 'webpack-zepto';
    import {CommentList} from './comment_list';
    import {CommentForm} from './comment_form';
    
    class CommentBox extends React.Component{
        constructor(props){
            super(props)
            this.state = {data: []};
            this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
        }
    
        loadCommentsFromServer(){
            let _this = this;
            $.ajax({
                url:_this.props.url,
                dataType:'json',
                cache:false,
                success(data){
                    _this.setState({data:data});
                },
                error(xhr, status, err){
                     console.error(_this.props.url, status, err.toString());
                }
            })
        
        }
    
          componentDidMount(){
              this.loadCommentsFromServer();
              // setInterval(this.loadCommentsFromServer.bind(this),this.props.pollInterval);
          }
    
          handleCommentSubmit(comment){
              let comments = this.state.data;
              comment.id = Date.now();
              let newComments = [...comments,...comment];
              this.setState({
                  data:newComments
              });
    
              let _this = this;
    
              
              $.ajax({
                  url: _this.props.url,
                  dataType: 'json',
                  type: 'POST',
                  data: comment,
                  success(data) {
                    _this.setState({data: data});
                  },
                  error(xhr, status, err) {
                    _this.setState({data: comments});
                    console.error(_this.props.url, status, err.toString());
                  }
              })
          }
    
          render(){
              return(
                  <div className="commentBox">
                    <h1>Comments:</h1>
                   <CommentList data={this.state.data} />
                    <CommentForm onCommentSubmit={this.handleCommentSubmit} />
                  </div>
              );
          }
    }
    
    export {CommentBox};
  1. 由于在es6中使用类的构造函数constructor来代替了getInitialState,所以以前在getInitialState里声明的初始量要变化到在constructor

  2. 另外就是在组件上绑定的函数的this指向问题坑了我好久


    import React from 'react';
    class CommentForm extends React.Component{
        constructor(props){
            super(props);
            this.state = {author:'',text:''};
        }
    
        handleAuthorChange(e){
    
                this.setState({
                    author:e.target.value
                })
            
        }
    
        handleTextChange(e){
            this.setState({
                text:e.target.value
            })
        }
    
        handleSubmit(e){
            e.preventDefault();
            let author = this.state.author.trim(),
                text = this.state.text.trim();
    
            if(!text || !author){
                alert('请填写完整');
                return false;
            }
    
            this.props.onCommentSubmit({
                author:author,
                text:text
            });
    
            this.setState({
                author:'',
                text:''
            })
        }
    
        render(){
            return(
                <form className='commentForm' onSubmit={this.handleSubmit.bind(this)}>
                    <input type='text' placeholder='name' value={this.state.author}
                    onChange={e => this.handleAuthorChange(e)} />
                    <input type='text' placeholder='say something...' value={this.state.text}
                    onChange={this.handleTextChange.bind(this)} />
                    <input type='submit' value='Post' />
                </form>
            );
        }
    }
    
    export {CommentForm};

在这个组件中,我给两个input绑定了函数,一开始以为函数里的this指向的是组件本身,后来才发现是window,原因是onChange的回调是在浏览器全局对象执行的,此时的this并不指向定义的React组件部分,如果不用es6,它是默认绑定到组件上的,所以这里要修改this的指向:


    1. onChange={e => this.handleAuthorChange(e)}
    2. onChange={this.handleAuthorChange.bind(this)}
    3. constructor(props){        //在构造器里面绑定,推荐
            super(props)
            this.state = {data: []};
            this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
        }

具体的代码我已放到github上,有需要的可以参考:github
此外,有一篇关于react规范的文章有兴趣的也可以看看:react规范
以上只是一个初学者的的看法,如果有不足或者错误的地方,欢迎指出


horizontal
283 声望1 粉丝

下一篇 »
js编程小题