使用 dragula 重新排序时如何保留对象属性?
How to retain object attributes when re-ordering with dragula?
下面的代码用于从 API 端点获取颜色列表的简单组件。然后用户可以在左容器和右容器之间拖动颜色。在 componentDidMount
生命周期方法中,组件将 API 中的所有颜色作为具有以下属性的对象推送到组件的状态中:
{ id, name, index }
状态更新时,这些颜色会正确地放入左侧容器中。右边的容器仍然是空的。
在render
方法中,如果我添加一个记录器吐出availableColors
数组,每个对象都有一个名称、ID和索引。应该如此。例如:
{ id: 1, name: 'red', index: 0 }
但是当我将颜色从左侧容器拖放到右侧容器并执行 dragula on drop 回调时,我只能访问添加到右侧容器的每种颜色的 innerHTML
。这意味着我失去了对象的属性,比如它从 API.
获得的 ID
换句话说,我推入 newColorList
的地方,color.id
是空白的。我认为我的问题是我不应该使用以下方法获取删除的元素:
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
我应该如何修复此代码?
class DragApp extends Component {
constructor(props) {
super(props);
this.state = {
availableColors: [],
selectedColors: []
}
}
componentDidMount() {
fetch('/api/color-list.json')
.then(function(response) {
return response.json()
})
.then(function(json) {
var availableColors = [];
json.forEach(function(color, index) {
availableColors.push({ index, name: color.name, id: color.id })
});
this.setState({ availableColors });
}.bind(this))
.catch(function(ex) {
// handle failure
});
dragula([document.querySelector('#left'), document.querySelector('#right')])
.on('drop', function(el, _) {
const newColorList = [];
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
Array.from(selectedColorItems).forEach(function(color) {
// getIndexInParent returns index of element
const index = getIndexInParent(color);
newColorList.push({ index, name: color.innerHTML, id: color.id })
})
this.setState({ selectedColors: newColorList });
}.bind(this));
}
render() {
const colorsList = this.state.availableColors;
const colors = colorsList.map((color) =>
<li key={ color.id }>
{ color.name }
</li>
);
return (
<div className='wrapper'>
<ul id="left" className="container">
{ colors }
</ul>
<ul id="right" className="container"></ul>
</div>
)
}
}
我建议使用数据属性来存储你的颜色信息并在你放下 li 时检索它们:
class DragApp extends Component {
constructor(props) {
super(props);
this.state = {
availableColors: [],
selectedColors: []
}
}
componentDidMount() {
fetch('/api/color-list.json')
.then(function(response) {
return response.json()
})
.then(function(json) {
var availableColors = [];
json.forEach(function(color, index) {
availableColors.push({
index,
name: color.name,
id: color.id
})
});
this.setState({
availableColors
});
}.bind(this))
.catch(function(ex) {
// handle failure
});
dragula([document.getElementById('#left'), document.getElementById('#right')])
.on('drop', function(el, _) {
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
newColorList = Array.from(selectedColorItems).map(function(color) {
return {
index: color.dataset.index,
id: color.dataset.id,
name: color.text
};
});
this.setState({
selectedColors: newColorList
});
}.bind(this));
}
render() {
const colorsList = this.state.availableColors;
const colors = colorsList.map((color) =>
<li key = { color.id } data-id="{ color.id }" data-index="{ color.index }">
{ color.name }
</li>
);
return (
<div className='wrapper'>
<ul id="left" className="container">
{ colors }
</ul>
<ul id="right" className="container"> </ul>
</div>
)
}
}
如果你想保持getIndexInParent
的想法,你应该使用array.find()
var getIndexInParent = function getIndexInParent(id) {
return this.state.availableColors.find(function(color) {
return color.id == id;
});
};
下面的代码用于从 API 端点获取颜色列表的简单组件。然后用户可以在左容器和右容器之间拖动颜色。在 componentDidMount
生命周期方法中,组件将 API 中的所有颜色作为具有以下属性的对象推送到组件的状态中:
{ id, name, index }
状态更新时,这些颜色会正确地放入左侧容器中。右边的容器仍然是空的。
在render
方法中,如果我添加一个记录器吐出availableColors
数组,每个对象都有一个名称、ID和索引。应该如此。例如:
{ id: 1, name: 'red', index: 0 }
但是当我将颜色从左侧容器拖放到右侧容器并执行 dragula on drop 回调时,我只能访问添加到右侧容器的每种颜色的 innerHTML
。这意味着我失去了对象的属性,比如它从 API.
换句话说,我推入 newColorList
的地方,color.id
是空白的。我认为我的问题是我不应该使用以下方法获取删除的元素:
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
我应该如何修复此代码?
class DragApp extends Component {
constructor(props) {
super(props);
this.state = {
availableColors: [],
selectedColors: []
}
}
componentDidMount() {
fetch('/api/color-list.json')
.then(function(response) {
return response.json()
})
.then(function(json) {
var availableColors = [];
json.forEach(function(color, index) {
availableColors.push({ index, name: color.name, id: color.id })
});
this.setState({ availableColors });
}.bind(this))
.catch(function(ex) {
// handle failure
});
dragula([document.querySelector('#left'), document.querySelector('#right')])
.on('drop', function(el, _) {
const newColorList = [];
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
Array.from(selectedColorItems).forEach(function(color) {
// getIndexInParent returns index of element
const index = getIndexInParent(color);
newColorList.push({ index, name: color.innerHTML, id: color.id })
})
this.setState({ selectedColors: newColorList });
}.bind(this));
}
render() {
const colorsList = this.state.availableColors;
const colors = colorsList.map((color) =>
<li key={ color.id }>
{ color.name }
</li>
);
return (
<div className='wrapper'>
<ul id="left" className="container">
{ colors }
</ul>
<ul id="right" className="container"></ul>
</div>
)
}
}
我建议使用数据属性来存储你的颜色信息并在你放下 li 时检索它们:
class DragApp extends Component {
constructor(props) {
super(props);
this.state = {
availableColors: [],
selectedColors: []
}
}
componentDidMount() {
fetch('/api/color-list.json')
.then(function(response) {
return response.json()
})
.then(function(json) {
var availableColors = [];
json.forEach(function(color, index) {
availableColors.push({
index,
name: color.name,
id: color.id
})
});
this.setState({
availableColors
});
}.bind(this))
.catch(function(ex) {
// handle failure
});
dragula([document.getElementById('#left'), document.getElementById('#right')])
.on('drop', function(el, _) {
const targetContainer = document.querySelector('#right');
const selectedColorItems = targetContainer.getElementsByTagName("li");
newColorList = Array.from(selectedColorItems).map(function(color) {
return {
index: color.dataset.index,
id: color.dataset.id,
name: color.text
};
});
this.setState({
selectedColors: newColorList
});
}.bind(this));
}
render() {
const colorsList = this.state.availableColors;
const colors = colorsList.map((color) =>
<li key = { color.id } data-id="{ color.id }" data-index="{ color.index }">
{ color.name }
</li>
);
return (
<div className='wrapper'>
<ul id="left" className="container">
{ colors }
</ul>
<ul id="right" className="container"> </ul>
</div>
)
}
}
如果你想保持getIndexInParent
的想法,你应该使用array.find()
var getIndexInParent = function getIndexInParent(id) {
return this.state.availableColors.find(function(color) {
return color.id == id;
});
};