React.js: 如何更改组件项的位置

React.js: How do you change the position of a Component item

如何在 React 中更改组件项的位置?

除非我误解了,React orders list items by key,在 DOM 中表示为 data-reactid,但我不知道如何修改页面上 key 个组件。

即如何抓取组件,更改它的 key,然后触发渲染,以便重新排序的列表按照您设置的顺序呈现?

例如在下面的代码示例中,当单击 Click me link 时,第一个列表项将与最后一个列表项交换。

理想情况下,此功能允许您动态 reorder/relocate 页面上的任何组件,而无需更改 render 方法中组件的顺序。

这里是一个 link 到整个项目所在的 repo:https://github.com/bengrunfeld/gae-react-flux-todos

var TodoBox = React.createClass({
  render: function(){
    return (
      <div className="todo-container">
        <h4>GAE React Flux Todos</h4>
        <TodoList data={this.state.data} />
      </div>
    )
  }
});

var TodoList = React.createClass({
  changePosition: function(e){
    // Change position of list item (e.g. to top/certain position/end of list)
  },
  render:function(){
    var todoNodes = this.props.data.map(function(todo) {
      return (
        <Todo key={todo.id} id={todo.id}>
          {todo.todoText}
        </Todo>
      );
    });
    return (
      <form className="todoList">
        {todoNodes}
        <a onClick={this.changePosition}>Click me</a>
      </form>
    )
  }
});

var Todo = React.createClass({
  render:function(){
    return (
      <div className="todoItem">
        <input type="text" className={this.props.id} onChange={this.checkInput} defaultValue={this.props.children} ref="todoItem"/>
      </div>
    )
  }
});

key 属性不用于对元素进行排序,而是用于在不同的 render 调用之间协调它。具有相同 key 的元素将不会是 re-rendered 而是相互区分以最佳地更新 DOM。参见 Reconciliation

如果你想重新排序元素,你需要改变它们在你的 JSX 中的位置,或者在你作为 children 在你的 render 方法中传递的元素数组中的位置 (todoNodes) .

在您的情况下,您可以在 TodoList 组件状态下制作 this.props.data 的副本,然后在 changePosition 方法中使用 this.setState({data: reorderedData}) 之类的内容更新该副本.制作该副本的好地方是 getInitialState.

然后将再次调用 TodoListrender 方法,并且您将映射到新重新排序的 this.state.data 以创建有序的 Todo 元素数组随你喜欢。

但是,请注意 props in getInitialState is an anti-pattern。由于您的数据存在于 TodoBox 组件的状态中,因此避免这种情况的一种方法是让 TodoList 组件在其 changePosition 方法中调用 this.props.onReorder(reorderedData)。然后,您的 TodoBox 组件可以将事件处理程序传递给它的 TodoList child,并在调用此处理程序时使用新数据更新其状态。

var TodoBox = React.createClass({
  handleReorder: function(reorderedData) {
    this.setState({data: reorderedData});
  },

  render: function(){
    return (
      <div className="todo-container">
        <h4>GAE React Flux Todos</h4>
        <TodoList data={this.state.data} onReorder={this.handleReorder} />
      </div>
    )
  }
});

var TodoList = React.createClass({
  changePosition: function(e){
    // Change position of list item (e.g. to top/certain position/end of list)
    // Create a copy of this.props.data and reorder it, then call
    // this.props.onReorder to signal to the parent component that
    // the data has been reordered
    this.props.onReorder(reorderedData);
  },

  render:function() {
    var todoNodes = this.props.data.map(function(todo) {
      return (
        <Todo key={todo.id} id={todo.id}>
          {todo.todoText}
        </Todo>
      );
    });
    return (
      <form className="todoList">
        {todoNodes}
        <a onClick={this.changePosition}>Click me</a>
      </form>
    )
  }
});

键用于其他用途,而不是用于排序。 React 使用 keys 来优化其内部虚拟 DOM 操作。这意味着你告诉 React "no matter the order of these siblings, the individual sibling is still identified by this key"。这就是 React 知道它是否应该通过重用旧的兄弟姐妹来添加、插入、删除或追加新兄弟姐妹的方式,而不会不必要地丢弃东西。

关于您的排序问题:要更改兄弟姐妹的顺序,只需对 JavaScript 数组 this.props.data.

进行排序即可