reactjs - 使用 ReactJs 通过 onclick 重新排序列表项
问题描述
学习 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)}>▲</span>
<span onClick={() => this.onMoveDown(key)}>▼</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);
解决方案
是的,您应该提升状态并提供回调onMoveUp/onMoveDown
并将它们传递给,FruitList
或者您可以拥有一个onMove(id: number, direction: number)
并传递到那里+1
(enum DOWN) 或-1
(enum UP) 以移动正确的方向。请参阅下面的代码。
如果您愿意,也可以将下面代码中的方法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)}>▲</a>
<a onClick={() => onMove(item.id, DOWN)}>▼</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>
推荐阅读
- python - 如何让 python 从列表中返回尽可能多的谜语
- wpf - UWP - 父控件拦截指针事件(其中子控件为 ScrollViewer)
- java - 如何在所有测试类完成后保存信息。Java Junit 5 Gradle
- python - 在 Python 中计算/估计 lognorm ppf 的快速方法
- python-3.x - pyttsx3 的问题:我的代码不说话
- vue.js - Fuse.js 抛出“未定义属性”错误并且搜索在页面加载时不起作用
- html - 在粘性元素上覆盖 CSS Stacking Context
- r - Geom_smooth 不在 ggplot2 上绘图
- java - JLabel 的弹出窗口上没有显示任何内容
- go - 如何将此 curl 调用转换为 Go?