添加了类,但立即将其删除

时间:2020-01-13 10:33:30

标签: javascript

我正在练习JS,并且一直在研究过滤机制。

可以在this小提琴中找到该代码。

我偶然发现了以下问题:

当我点击 size 过滤器时, foundSize 类似乎已添加到适当的元素中,无论如何 立即删除。您可以在控制台中观察到这一点。

我的猜测是嵌套循环中有问题,但我不知道这是什么。该问题可以在第132-138行找到,该行发生了添加/删除类。

for (let j = 0; j < filterableSizes.length; j++) {         
    const singleFilterableSize = filterableSizes[j].dataset.size;           
    if( activeFilterArray.indexOf(filterableSizes[j].dataset.size) > -1 ) { 
      filterables[i].classList.add('foundSize'); 
    } else {              
      filterables[i].classList.remove('foundSize'); 
    }
  }

为什么会这样?我该如何解决?

谢谢:)

function createSizeFilters() {
    
    const sizeFilterWrapper = document.querySelector('.size-filter-wrapper');
    const sizesFromProducts = Array.from(document.querySelectorAll('.a-product label'));
    const sizesNames = sizesFromProducts.map(sizeName => sizeName.textContent);    
    const uniqSizes = [ ...new Set(sizesNames) ];
    const uniqSizesValues = uniqSizes.values();
    let cnt1 = 1;
    let cnt2 = 1;
    for (const value of uniqSizesValues) { 

      const sizeOption = document.createElement('div');
      sizeOption.classList.add('size-option');
      sizeOption.setAttribute('data-size', `${value}`);

      const sizeOptionLabel = document.createElement('label');
      sizeOptionLabel.classList.add('option-label', 'size-label');
      sizeOptionLabel.textContent = value;
      sizeOptionLabel.setAttribute('for', `size-input-${cnt1++}`);

      const sizeInput = document.createElement('input');
      sizeInput.classList.add('filter-input', 'size-input');
      sizeInput.setAttribute('type', 'checkbox');
      sizeInput.setAttribute('id', `size-input-${cnt2++}`);
      sizeInput.setAttribute('value', `${value}`); 
      sizeInput.setAttribute('name', `${value}`);     
      sizeOption.appendChild(sizeOptionLabel);
      sizeOption.appendChild(sizeInput);      
      sizeFilterWrapper.appendChild(sizeOption);
    }
 
}
  

function createColorFilters() {
    
    const colorFilterWrapper = document.querySelector('.color-filter-wrapper');
    const colorsFromProducts = Array.from(document.querySelectorAll('.a-product'));
    const colorsNames = colorsFromProducts.map(colorName => colorName.dataset.color);
    const uniqColors = [ ...new Set(colorsNames) ];
    const uniqColorsValues = uniqColors.values();
    let cnt1 = 1;
    let cnt2 = 1;
    for (const value of uniqColorsValues) { 
      
      const colorOption = document.createElement('div');
      colorOption.classList.add('color-option');
      colorOption.setAttribute('data-color', `${value}`);
      
      const colorOptionLabel = document.createElement('label');
      colorOptionLabel.classList.add('option-label', 'color-label');
      colorOptionLabel.textContent = value;
      colorOptionLabel.setAttribute('for', `color-input-${cnt1++}`);
      
      const colorInput = document.createElement('input');
      colorInput.classList.add('filter-input', 'color-input');
      colorInput.setAttribute('type', 'checkbox');
      colorInput.setAttribute('id', `color-input-${cnt2++}`);
      colorInput.setAttribute('value', `${value}`); 
      colorInput.setAttribute('name', `${value}`);
      
      colorOption.appendChild(colorOptionLabel);
      colorOption.appendChild(colorInput);
      
      colorFilterWrapper.appendChild(colorOption);
    }
   
    
}
  

async function filterProducts() {      
    const filters = document.querySelectorAll('.filter-input');        
    let activeFilterArray = [];      
    await getActiveFilters(filters, activeFilterArray);         
}
    

function getActiveFilters(filters, activeFilterArray) {  
  for (let i = 0; i < filters.length; i++) {
    filters[i].addEventListener('change', function() { 
      const filterTerm = this.value,
            filterState = this.checked,
            filterParentCat = this.parentNode.parentNode.dataset.filtercategory;
      this.classList.toggle('active-filter');
      this.previousElementSibling.classList.toggle('bold');

      if(filterState == true) { 
        activeFilterArray.push(filterTerm);   
      } else {     
        activeFilterArray.splice( activeFilterArray.indexOf(filterTerm), 1 );
      }

      
      filterFilterables(activeFilterArray); 

    });
  }
}
  
  

function filterFilterables(activeFilterArray) {

  const filterables = document.querySelectorAll('.a-product');
  for (let i = 0; i < filterables.length; i++) {


    if( (activeFilterArray.length > 0) ) { 

      // COLORS ~~~~~~~~~~~~~~~
      // ~~~~~~~~~~~~~~~~~~~~~~
      const filterableColor = filterables[i].dataset.color;
      if( activeFilterArray.indexOf(filterableColor) > -1 ) {         
        filterables[i].classList.add('foundColor'); 
      } else {
        filterables[i].classList.remove('foundColor');         
      }


      // SIZES ~~~~~~~~~~~~~~~~
      // ~~~~~~~~~~~~~~~~~~~~~~
      const filterableSizes = filterables[i].querySelectorAll('.a-swatch');
      console.log(filterableSizes);

      for (let j = 0; j < filterableSizes.length; j++) {         
        const singleFilterableSize = filterableSizes[j].dataset.size;           
        if( activeFilterArray.indexOf(filterableSizes[j].dataset.size) > -1 ) { 
          filterables[i].classList.add('foundSize'); 
        } else {              
          filterables[i].classList.remove('foundSize'); 
        }
      }

    } else {

      filterables[i].classList.remove('foundColor');
      filterables[i].classList.remove('foundSize'); 

    }

  }

}

createSizeFilters();
createColorFilters();
filterProducts();
.filterables, .filters-wrapper { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; }
.a-product { width: 100px; height: 100px; border: 2px solid black; }
<section class="the-collection-products">
  
	<div class="filters-wrapper">
				  
		<!-- Size Filters -->
		<div>
			<span>Size</span>
			<div class="filter-wrapper size-filter-wrapper" id="size-filter-wrapper" data-filtercategory="Size Filters"></div>
		</div>

		<!-- Color Filters -->
		<div>
			<span>Color</span>
			<div class="filter-wrapper color-filter-wrapper" id="color-filter-wrapper" data-filtercategory="Color Filters"></div>
		</div>
				
	</div>
  
  <br/> <br/> <br/>


	<div class="filterables">

		<div class="a-product" data-available="true" data-color="Blue" data-sustainable="yes">
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg disabled foundSize" data-size="SM">
				<label class="vhf-center z1 disabled" for="product-31021058785368">SM</label>	
				<input id="product-31021058785368" type="radio" name="SM" data-size="SM">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="M">
				<label class="vhf-center z1" for="product-31021058818136">M</label>	
				<input id="product-31021058818136" type="radio" name="M" data-size="M">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="L">
				<label class="vhf-center z1" for="product-31021058850904">L</label>	
				<input id="product-31021058850904" type="radio" name="L" data-size="L">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="XL">
				<label class="vhf-center z1" for="product-31021058883672">XL</label>	
				<input id="product-31021058883672" type="radio" name="XL" data-size="XL">
			</div>
		</div>


		<div class="a-product" data-available="true" data-color="Red" data-sustainable="">		
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="M">
				<label class="vhf-center z1" for="product-31021096075352">M</label>	
				<input id="product-31021096075352" type="radio" name="M" data-size="M">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg disabled" data-size="L">
				<label class="vhf-center z1 disabled" for="product-31021096108120">L</label>	
				<input id="product-31021096108120" type="radio" name="L" data-size="L">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="XL">
				<label class="vhf-center z1" for="product-31021096140888">XL</label>	
				<input id="product-31021096140888" type="radio" name="XL" data-size="XL">
			</div>
		</div>


		<div class="a-product" data-available="true" data-color="Green" data-sustainable="">	
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg foundSize" data-size="SM">
				<label class="vhf-center z1" for="product-31021083852888">SM</label>	
				<input id="product-31021083852888" type="radio" name="SM" data-size="SM">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="M">
				<label class="vhf-center z1" for="product-31021083885656">M</label>	
				<input id="product-31021083885656" type="radio" name="M" data-size="M">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="L">
				<label class="vhf-center z1" for="product-31021083918424">L</label>	
				<input id="product-31021083918424" type="radio" name="L" data-size="L">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="XL">
				<label class="vhf-center z1" for="product-31021083951192">XL</label>	
				<input id="product-31021083951192" type="radio" name="XL" data-size="XL">
			</div>
		</div>


		<div class="a-product" data-available="true" data-color="White" data-sustainable="yes">
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="Size Free">
				<label class="vhf-center z1" for="product-31257402638424">Size Free</label>	
				<input id="product-31257402638424" type="radio" name="Size Free" data-size="Size Free">
			</div>
		</div>
			
	
		<div class="a-product" data-available="true" data-color="White" data-sustainable="">			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="Size Free">
				<label class="vhf-center z1" for="product-31257393168472">Size Free</label>	
				<input id="product-31257393168472" type="radio" name="Size Free" data-size="Size Free">
			</div>
		</div>


		<div class="a-product" data-available="true" data-color="White" data-sustainable="">			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="Size Free">
				<label class="vhf-center z1" for="product-31257394348120">Size Free</label>	
				<input id="product-31257394348120" type="radio" name="Size Free" data-size="Size Free">
			</div>
		</div>


		<div class="a-product" data-available="true" data-color="Blue" data-sustainable="">			         
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg foundSize" data-size="SM">
				<label class="vhf-center z1" for="product-31024749936728">SM</label>	
				<input id="product-31024749936728" type="radio" name="SM" data-size="SM">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg disabled" data-size="M">
				<label class="vhf-center z1 disabled" for="product-31024749969496">M</label>	
				<input id="product-31024749969496" type="radio" name="M" data-size="M">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg disabled" data-size="L">
				<label class="vhf-center z1 disabled" for="product-31024750002264">L</label>	
				<input id="product-31024750002264" type="radio" name="L" data-size="L">
			</div>
			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg disabled" data-size="XL">
				<label class="vhf-center z1 disabled" for="product-31024750035032">XL</label>	
				<input id="product-31024750035032" type="radio" name="XL" data-size="XL">
			</div>
		</div>

			
		<div class="a-product" data-available="true" data-color="Black" data-sustainable="">			
			<div class="a-swatch size-swatch relative vhf-center flex-column-lg" data-size="Size Free">
				<label class="vhf-center z1" for="product-31257301221464">Size Free</label>	
				<input id="product-31257301221464" type="radio" name="Size Free" data-size="Size Free">
			</div>
		</div>

			

	</div>


</section>
  
  
  	

1 个答案:

答案 0 :(得分:1)

为什么会这样

之所以发生这种情况,是因为filterableSizes循环在找到任何选定的大小时分配了foundSize,但是您正在循环所有大小,并且对于未选择的每个大小,它都会失败。

换句话说,您选择SM并期望具有small属性的每个项目都具有一个foundSize类,但是代码为每个项目都这样做:

  1. 我选择的(sm)过滤器是否匹配拳头尺寸(sm)->是->分配foundSize

  2. 我选择的(sm)过滤器是否与第二个尺寸(M)相匹配->否->删除foundSize

我该如何解决?

找到大小后,中断内部循环。

for (let j = 0; j < filterableSizes.length; j++) {         
    const singleFilterableSize = filterableSizes[j].dataset.size;           
    if( activeFilterArray.indexOf(filterableSizes[j].dataset.size) > -1 ) { 
      filterables[i].classList.add('foundSize'); 
      break;
    } 
    filterables[i].classList.remove('foundSize'); 
  }