ReactJS修炼之路(一)

一,相关学习资料

先放一些前期看过的以及正在看的资料,初学者,会一边学习一边实践。

  • 官方文档
  • 官方入门教程
  • React生命周期

二,javascript深坑

从来都没有学过javascript,写倒是写了一些,所以下面提及那个坑也是被坑得心服口服。

问题描述:
在给button设置onClick点击行为的时候,点击按钮死活执行对应的函数,Google了一下,在stack-overflow上找到一些类似的问题,英文是when I click the button, it don’t fired(觉得fired好玩就摘抄了下来)。

不多说,直接上正确代码。

    deleteProgram: function(){
        alert("delete");
    },
    render: function(){
    var that = this;  //去掉这行有惊喜
    return(
      <ul>
      {
        this.state.programs.map(function(bill,index) {
          return <li>
          <ChannelProgram start_time={bill["start_time"]} end_time={bill["end_time"]} title={bill["program"]["name"]}/>
          <button onClick={that.deleteProgram} value={index}>Deletebutton>  //注意这个是用的that
          li>;
        })
      }
      </ul>
    );
  }

注意第五行代码(话说markdown怎么添加代码行号,求指点,这里网速不好就先不Google了,以后找到会再分享,12月9日更新,发了博客后会自动加上代码行号

var that = this;  //去掉这行有惊喜

下面是错误的代码:

    deleteProgram: function(){
        alert("delete");
    },
    render: function(){
    return(
      <ul>
      {
        this.state.programs.map(function(bill,index) {
          return <li>
          <ChannelProgram start_time={bill["start_time"]} end_time={bill["end_time"]} title={bill["program"]["name"]}/>
          <button onClick={this.deleteProgram} value={index}>Deletebutton>  //注意这个是用的this
          li>;
        })
      }
      </ul>
    );
  }

对于一个近期在写C++的人来说,上面的代码毫无违和感,但是问题来了。

下面这个this到底是谁的上下文呢?答案:当前function内的。所以上面的代码为什么点击按钮没有触发对应的代码,就是因为没有当前function里没有这个函数。而我们的意思是要找到外面的deleteProgram函数。这就是为什么需要用这句代码:

var that = this;  //去掉这行有惊喜

在进入一个新的函数前,先用这行代码把之前的上下文保存下来,否则this会被更新成当前的function的this。

  • javascript的this是当前function内的上下文。
  • javascript的this是当前function内的上下文。
  • javascript的this是当前function内的上下文。

三,React复合组件内容更新的坑

晚上写完代码补充
12月9日更新,果然晚上是没有时间补上的,趁现在有时间赶紧写下来。

问题描述:
在复合组件里,即便父级组件刷新了(调用了render函数来刷新界面),子级组件的值也不更新。
老规矩,不多说,直接上代码。

Channel部分代码

render: function(){
    var that = this;
    return(
        <ul>
        {
          this.state.programs.map(function(bill,index) {
            return <li><ChannelProgram change={that.props.change} start_time={bill["start_time"]} end_time={bill["end_time"]} title={bill["program"]["name"]}/>li>;
          })
        }
        </ul>
    );
  }

ChannelProgram组件内部代码

var ChannelProgram = React.createClass({
  getInitialState: function() {
    return {
      start_time: this.props.start_time,
      end_time: this.props.end_time,
      title: this.props.title
    }
  },
  componentWillReceiveProps: function(nextProps,nextState) {
    this.setState({
      start_time: nextProps.start_time,
      end_time: nextProps.end_time,
      title: nextProps.title
    });
  },
  render: function(){
    var start_time = this.state.start_time;
    var end_time = this.state.end_time;
    var title = this.state.title;
    return(
        <div>
          <input id="start_time" value={start_time} onChange={this.props.change}/>
          <input id="end_time" value={end_time} onChange={this.props.change}/>
          <input id="title" value={title} onChange={this.props.change}/>
        div>
      );
  }
});

注意上面ChannelProgram里面的第十行开始的函数,更新子组件的关键:

  componentWillReceiveProps: function(nextProps,nextState) {
    this.setState({
      start_time: nextProps.start_time,
      end_time: nextProps.end_time,
      title: nextProps.title
    });
  }

如果看过开头提及的资料《React生命周期》,那一切问题都不是问题了,所以像我这种新手还是要先看文档再上手写代码省事得多,不过项目进度要跟上,暂且现学现用。

componentWillReceiveProps,理解意思即可,组件收到新的props时会触发(即当父级组件render刷新了子组件的props时触发),此时更新状态,大功告成。

好了,看似简单,我说说我的想法和困惑的地方。一开始我是没有加上这个函数的,导致子组件内容不更新,很疑惑,明明父级组件的render刷新了,子组件就是不更新。后来在子组件的getInitialState函数里面输出log,发现无论父级组件更新了多少次,子组件的getInitialState只会执行一遍。恍然大悟,React的刷新机制是重用已有组件而不是重新新建组件(如果新建组件的话,每次刷新getInitialState都会被调用),如果一开始就从React的原理出发考虑问题,就不会走弯路了,不过弯路走得越多越深刻吧,加油就好!

四,其他

这里提到的坑都不是React和javascript的问题,都是自己学艺不精所致,说是React和javascript的坑只是自嘲一下,理解为我在学习React和javascript时爬过的坑即可,也是本博客的本意。

你可能感兴趣的:(React)