我一直在尝试设置一个项目数组的过滤器,这样当用户点击复选框时,列表将只显示基于其选择的项目。它需要允许多个选择,以便多个条件中的任何一个(而不是全部)应用于过滤器。
下面的代码是我所拥有的,但它只将过滤器应用于第一个复选框,每次我选择第二个或第三个复选框时,过滤器都不会改变。
let filterOptions = document.querySelectorAll(".filter_checkbox")
var filterList = [];
const handleFilterCheckbox = (e) => {
for(var i=0; filterOptions[i]; i++){
if(filterOptions[i].checked){
filterList.push(filterOptions[i].value);
}
}
console.log(filterList)
var getFilteredResults = hotelsList.filter(function (result) {
for(var i=0; i < filterList.length; i++){
return filterList.indexOf(result.locationName) >= 0;
}
});
if(filterList.length > 0){
setHotelsList(getFilteredResults)
}else{
setHotelsList(hotels)
}
}
更新:下面是完整的代码
import { useState } from 'react'
import './cards.styles.css'
import Card from '../card/Card'
import hotels from '../../data/hotels_array'
export default function Cards(){
const [hotelsList, setHotelsList] = useState(hotels)
const handleSortChange = (e) => {
const sortValue = e.target.value
const copyHotelsList = [...hotelsList]
if(sortValue === "sort-default"){
setHotelsList(hotels)
}else{
copyHotelsList.sort((a, b) => {
if(sortValue === "sort-price-lh"){
return a.fromPrice - b.fromPrice
}else if (sortValue === "sort-price-hl"){
return b.fromPrice - a.fromPrice
}else if(sortValue === "sort-review-score"){
return b.guestRating - a.guestRating
}
})
setHotelsList(copyHotelsList)
}
}
const hotelCards = hotelsList.map(hotel =>{
return (
<Card
key={hotel.hotelId}
{...hotel}
/>
)
})
const hotelsListUniqueByLocation = [...new Map(hotels.map(item => [item.locationName, item])).values()];
let filterOptions = document.querySelectorAll(".filter_checkbox")
var filterList = [];
const handleFilterCheckbox = (e) => {
for(var i=0; filterOptions[i]; i++){
if(filterOptions[i].checked){
filterList.push(filterOptions[i].value);
}
}
console.log(filterList)
var getFilteredResults = hotelsList.filter(function (result) {
for(var i=0; i < filterList.length; i++){
return filterList.indexOf(result.locationName) >= 0;
}
});
if(filterList.length > 0){
setHotelsList(getFilteredResults)
}else{
setHotelsList(hotels)
}
}
const hotelLocations = hotelsListUniqueByLocation.map(location =>{
if(location.locationName != ""){
return (
<li key={location.locationName}>
<input type="checkbox" id={location.locationName} value={location.locationName} onChange={handleFilterCheckbox} className="filter_checkbox" />
<label htmlFor={location.locationName} className='fs12p'>{location.locationName}</label>
</li>
)
}
})
return(
<div className="results_container">
<aside>
<h3>Filter</h3>
Sorted by:
<select onChange={handleSortChange}>
<option value="sort-default">Recommended</option>
<option value="sort-price-lh">Price (low to high)</option>
<option value="sort-price-hl">Price (high to low)</option>
<option value="sort-review-score">Review score</option>
</select>
<div>
<input type="checkbox" value="wififree" id="wififree" className="filter_checkbox" />
<label htmlFor="wififree" className='fs12p'>Free Wi-Fi</label>
</div>
<div>
<ul className='hotel_locations'>
{hotelLocations}
</ul>
</div>
</aside>
<section className='cards_container container'>
{hotelCards}
</section>
</div>
)
}
2条答案
按热度按时间okxuctiv1#
我认为问题出在
getFilteredResults
上您将检查过滤器,但如果其中一个匹配,则返回
true
,因此不检查其他过滤器为了确保所有过滤器都匹配,可以使用
every
函数ymdaylpp2#
关键是将过滤器存储为状态,复选框会更新状态,然后可以使用函数生成相关数据:复选框的值,控制是否选中它们,以及酒店列表的对象。
我在您添加完整代码之前编写了此代码,因此它略有不同,但它应该显示复选框位置过滤器如何缩小酒店列表的范围。
注1:我没有在组件中使用函数,因为我可以将各种状态作为参数传递给它们,这主要意味着如果需要,可以将它们解耦到帮助文件中,使组件更简洁和干净。
注2:我在这里使用event delegation来捕获复选框事件,因为它们在DOM中"冒泡",但是向复选框添加单独的侦听器也是可以的--这样做更简洁一些。