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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29020771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:58:35  来源:igfitidea点击:

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

javascriptreactjs

提问by Ben

How do you change the position of a Component item in React?

你如何改变 React 中组件项的位置?

Unless I've misunderstood it, React orders list items by key, which is represented in the DOM by data-reactid, but I don't know how to modify the keyof components on the page.

除非我理解错了,React 将列表项按 by 排序key,在 DOM 中表示为 by data-reactid,但我不知道如何修改key页面上的组件。

i.e. How do you grab the component, change it's key, and then fire a render so that the reordered list renders in the order you've set?

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

e.g. in the following code example, when the Click melink is clicked, the first list item would be swapped with the last list item.

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

Ideally, this functionality would allow you to dynamically reorder/relocate any component on the page without changing the order of components in the rendermethod.

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

Here is a link to the repo where the full project is located: https://github.com/bengrunfeld/gae-react-flux-todos

这是完整项目所在的 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>
    )
  }
});

回答by Alexandre Kirszenberg

The keyprop is not used to order the element, but to reconciliate it between different rendercalls. Elements with the same keywill not be re-rendered but rather diffed against each other in order to update the DOM optimally. See Reconciliation

key道具不用于排序元素,但不同之间reconciliate它render调用。具有相同元素的元素key不会被重新渲染,而是会相互区分,以便以最佳方式更新 DOM。见对帐

If you want to reorder elements, you need to change their position in your JSX or in the element array you pass as children in your rendermethod (todoNodes).

如果要对元素重新排序,则需要更改它们在 JSX 或在render方法 ( todoNodes) 中作为子项传递的元素数组中的位置。

In your case, you could make a copy of this.props.datain the TodoListcomponent state, then update that copy in your changePositionmethod with something like this.setState({data: reorderedData}). A good place to make that copy would be in getInitialState.

在您的情况下,您可以this.props.dataTodoList组件状态中创建一个副本,然后在您的changePosition方法中使用类似this.setState({data: reorderedData}). 制作该副本的好地方是getInitialState.

The rendermethod of your TodoListwould then be called again, and you would map over your newly reordered this.state.datato create an array of Todoelements ordered to your liking.

然后将再次调用render您的方法,您TodoList将映射新重新排序this.state.dataTodo元素以创建一个按您的喜好排序的元素数组。

However, be aware that props in getInitialStateis an anti-pattern. Since your data lives in the state of your TodoBoxcomponent, a way to avoid this would be to have your TodoListcomponent call this.props.onReorder(reorderedData)in its changePositionmethod. Your TodoBoxcomponent could then pass an event handler to its TodoListchild, and update its state with the new data whenever this handler is called.

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

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>
    )
  }
});

回答by Rygu

Keys are used for something else, not for sorting. React uses keys to optimize its internal Virtual DOM operations. It means you tell React that "no matter the order of these siblings, the individual sibling is still identified by this key". That's how React knows whether it should prepend, insert, delete, or append new siblings by reusing the old, without throwing stuff away unnecessarily.

键用于其他用途,而不是用于排序。React 使用keys 来优化其内部的 Virtual DOM 操作。这意味着你告诉 React “无论这些兄弟姐妹的顺序如何,单个兄弟姐妹仍然由这个键标识”。这就是 React 如何知道它是否应该通过重用旧的来添加、插入、删除或附加新的兄弟姐妹,而不会不必要地扔掉东西。

As for your sorting question: To change the order of the siblings, just sort the JavaScript array this.props.data.

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