33

下面的代码来自React,它动态更新 DOM。我使用了 Facebook react 的教程,但不理解整个代码,即代码的哪一部分在何时以及如何触发代码中的其余部分执行。请帮助我理解代码。

var TodoList = React.createClass({
  render: function() {
    var createItem = function(itemText) {
      return <li>{itemText}</li>;
    };
    return <ul>{this.props.items.map(createItem)}</ul>;
  }
});

var TodoApp = React.createClass({
  getInitialState: function() {
   return {items: [], text: ''};
  },

  onChange: function(e) {
    this.setState({text: e.target.value});
  },

  handleSubmit: function(e) {
    e.preventDefault();
    var nextItems = this.state.items.concat([this.state.text]);
    var nextText = '';
    this.setState({items: nextItems, text: nextText});
  },

  render: function() {
    return (
      <div>
        <h3>TODO</h3>
        <TodoList items={this.state.items} />
        <form onSubmit={this.handleSubmit}>
          <input onChange={this.onChange} value={this.state.text} />
          <button>{'Add #' + (this.state.items.length + 1)}</button>
        </form>
      </div>
    );
   }
});
React.renderComponent(<TodoApp />, mountNode);

上述代码用于动态更新 DOM 结构。此代码引用自http://facebook.github.io/react/,请帮助了解代码的工作过程。

4

2 回答 2

73

谢谢,这是一个非常好的问题。以下是幕后发生的事情的粗略概述:

初始化

一切都从这一行开始:

React.renderComponent(<TodoApp />, mountNode);

这将实例化 TodoApp 组件,该组件调用:

TodoApp::getInitialState()

然后,它呈现 TodoApp 组件

TodoApp::render()

依次实例化一个 TodoList

TodoList::render()

至此,我们拥有了渲染初始标记所需的一切

<div>
  <h3>TODO</h3>
  <ul></ul> <!-- <TodoList> -->
  <form>
    <input value="" />
    <button>Add #1</button>
  </form>
</div>

它被字符串化并通过 innerHTML 添加到 mountNode 内部

改变

然后假设您要在输入中输入一些文本,然后

TodoApp::onChange

将被调用,这将调用

TodoApp::setState

反过来会打电话

TodoApp::render

再次生成更新的 DOM

<div>
  <h3>TODO</h3>
  <ul></ul> <!-- <TodoList> -->
  <form>
    <input value="sometext" />
    <button>Add #1</button>
  </form>
</div>

此时发生的事情是 React 将在前一个 DOM 和当前 DOM 之间做一个差异。

    <div>
      <input
-       value=""
+       value="sometext"

只有输入的值发生了变化,所以 React 只会更新真实 DOM 中的这个特定属性。

于 2013-09-11T19:31:45.917 回答
1

你可以在React 官方页面上找到更一般的解释。通常,反应生命周期可以通过以下阶段来描述(一旦创建组件,可以重复多次):

初始化值(仅一次):

    constructor(){ ... }

安装,如果您需要在初始渲染后添加一些东西(仅一次):

    componentDidMount(){...}

重新渲染函数、变量和组件

    myArrowFunction = () => {
      ...
      this.setState({...})
      ...  
    }   

更新:

    componentDidUpdate()}{...}
    shouldComponentUpdate(){...}

卸载:

    componentWillUnmount(){...}

渲染发生在这里

    render(){...}
于 2018-12-18T01:00:52.410 回答