使用ReactJs通过onclick对列表项进行重新排序

时间:2018-10-30 14:32:53

标签: reactjs

学习ReactJs,我将使用最佳实践来实现这一点。请任何人添加其他功能或对您的解决方案发表评论。

我试图通过单击一组向上/向下按钮来构建重新排序列表项组件。

1)我如何显示所有道具组件值及其bgColor?

2)为了处理事件,我必须使用构造函数并在内部添加onClickUp()和onClickDown()方法?

FruitList组件:

class FruitList extends Component {

   constructor(props) {
      super(props);
      this.state = { // set new state for bind key items
         items : [
           {'id': 1, 'name': 'orange', 'bgColor': '#f9cb9c'},
           {'id': 2, 'name': 'lemon','bgColor' : '#fee599'},
           {'id': 3, 'name': 'strawberry', 'bgColor': '#e06666'},
           {'id': 4, 'name': 'apple', 'bgColor' : '#b6d7a7'}
         ]
      }
   }

   onMoveUp = (key) => {
      if(key === 0) return; // disable method when the key its equal to 0 
      const { items } = this.props; // assign props to items for don't repeat my self 
      const index = key - 1;  // save in memory index value less than one
      const itemAbove = items[index]; // save in memory items index  
      items[key - 1] = items[key]; // match id value with the key object
      items[key] = itemAbove; 
      this.setState({ items }); // set new state 
   }

   onMoveDown = (key) => {
      const { items } = this.props;
      if(key === items.length - 1) return;
      const index = key + 1;
      const itemBelow = items[index];
      items[key + 1] = items[key];
      items[key] = itemBelow;
      this.setState({ items });
   }

   render() {
      const { items } = this.state;

      return (
         <ul>
           {items.map((item, key) =>
               <li key={key} style={{ backgroundColor: item.bgColor }}>
                  <div className="fruitsId">{ key + 1 }</div>
                  <div className="fruitsName">{ item.name }</div>
                  <div className="fruitsArrows">
                     <span onClick={() => this.onMoveUp(key)}>&#x25B2;</span>
                     <span onClick={() => this.onMoveDown(key)}>&#x25BC;</span>
                  </div>
               </li>
            )}
         </ul>
      );
   }

}

App.js组件:

class App extends Component {

   constructor(props) {
      super(props);
      this.state = {
         fruitList : [
           {'id': 1, 'name': 'orange', 'bgColor': '#f9cb9c'},
           {'id': 2, 'name': 'lemon','bgColor' : '#fee599'},
           {'id': 3, 'name': 'strawberry', 'bgColor': '#e06666'},
           {'id': 4, 'name': 'apple', 'bgColor' : '#b6d7a7'}
         ]         
      }
   }

   render() {
      return (
         <FruitList items={this.state.fruitList} />
      );
   }

}

ReactDOM.render(<App />, document.body);

SandBox Demo

2 个答案:

答案 0 :(得分:0)

是的,您应该lift the sate up并提供回调onMoveUp/onMoveDown并将其传递给FruitList,或者您可以拥有一个onMove(id: number, direction: number)并传递+1(枚举DOWN )或-1(向上枚举)向右移动。请参见下面的代码。

如果需要,可以将下面代码中的方法handleMove移到FruitList类中,并命名为handleListChanged这样,App仅在每个时间改变了。我猜我的代码对您来说更好,因为您是从React开始的。

const UP = -1
const DOWN = 1

class FruitList extends React.Component {
   render() {
      const {fruitList, onMove} = this.props

      return (
         <ul>
           {fruitList.map((item) =>
               <li key={item.id} style={{ backgroundColor: item.bgColor }}>
                  <div className="fruitsId">{item.id}</div>
                  <div className="fruitsName">{item.name}</div>
                  <div className="fruitsArrows">
                     <a onClick={() => onMove(item.id, UP)}>&#x25B2;</a>
                     <a onClick={() => onMove(item.id, DOWN)}>&#x25BC;</a>
                  </div>
               </li>
            )}
         </ul>
      );
   }
}

class App extends React.Component {
  state = { // set new state for bind key items
    items: [
      {'id': 1, 'name': 'orange', 'bgColor': '#f9cb9c'},
      {'id': 2, 'name': 'lemon','bgColor' : '#fee599'},
      {'id': 3, 'name': 'strawberry', 'bgColor': '#e06666'},
      {'id': 4, 'name': 'apple', 'bgColor' : '#b6d7a7'},
    ]
  }

  handleMove = (id, direction) => {
    const {items} = this.state

    const position = items.findIndex((i) => i.id === id)
    if (position < 0) {
      throw new Error("Given item not found.")
    } else if (direction === UP && position === 0 || direction === DOWN && position === items.length - 1) {
      return // canot move outside of array
    }

    const item = items[position] // save item for later
    const newItems = items.filter((i) => i.id !== id) // remove item from array
    newItems.splice(position + direction, 0, item)

    this.setState({items: newItems})
  }

  render() {
    return (
      <FruitList fruitList={this.state.items} onMove={this.handleMove} />
    )
  }
}

ReactDOM.render(
  <App />,
  document.body
);
/* Add your css styles here */
body {
    font-family: Arial, Helvetica, sans-serif;
}
ul {
    list-style: none;
    padding: 0;
}
li {
    margin: 0 auto;
    text-align: center;
    width: 400px;
    display: flex;
    align-items: center;    
    justify-content: center;
}
li div {
    border: 1px solid white;
    padding: 5px 0;
}
.fruitsId,
    .fruitsArrows {
    width: 50px;
}
.fruitsName {
    width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

答案 1 :(得分:0)

您遇到了几个问题。首先,您需要映射水果清单中各项的属性,并且bgColor的变量必须一致。请参阅下面的功能示例,至少可以开始使用功能正常的组件:

class FruitsList extends React.Component {
   render() {
      return (
         <ul>
           {this.props.items.map((item, key) =>
               <li style={{ backgroundColor: item.bgColor }}>
                  <div className="fruitsId">{ item.id }</div>
                  <div className="fruitsName">{ item.name }</div>
                  <div className="fruitsArrows">
                     <span>&#x25B2;</span>
                     <span>&#x25BC;</span>                    
                  </div>
               </li>            
            )}
         </ul>
      );
   }
}

FruitsList.defaultsProps = {Items:[]}

class App extends React.Component {
  state = {
     fruitsList : [
       { 'id': 1, 'name': 'orange', 'bgColor': '#f9cb9c'},
       { 'id': 2, 'name': 'lemon','bgColor' : '#fee599'},
       { 'id': 3, 'name': 'strawberry', 'bgColor': '#e06666'},
       { 'id': 4, 'name': 'apple', 'bgColor' : '#b6d7a7'}
     ]         
  } 
   render() {
      return (
         <FruitsList items={this.state.fruitsList} />
      );
   }
}

ReactDOM.render(
  <App />,
  document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>