Преобразование повторяющегося кода jQuery в чистый код

#javascript #jquery #html #css

#javascript #jquery #HTML #css

Вопрос:

Итак, у меня есть этот код, но я подумал, что он слишком повторяющийся, у кого-нибудь есть идея, как я мог бы это сделать? Когда я загружаю новое изображение, я хочу, чтобы отображалось новое окно изображения. Мое решение работает, но что, если я хотел бы иметь 1000 новых изображений? Я не могу просто ввести один за раз. Что я мог бы сделать, чтобы оптимизировать эту проблему?

HTML:

 <div class="wrapper">
    <div class="box box_image" id="box_image_1">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image1" data-show='box_image_2' name="IgniteFormObject.Image1" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_2">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image2" data-show='box_image_3' name="IgniteFormObject.Image2" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_3">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image3" data-show='box_image_4' name="IgniteFormObject.Image3" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_4">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image4" data-show='box_image_5' name="IgniteFormObject.Image4" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
    <div class="box box_image" id="box_image_5">
        <div class="js--image-preview"></div>
        <div class="upload-options">
            <label>
                <input type="file" class="image-upload" id="image5" name="IgniteFormObject.Image5" accept="image/*" enctype="multipart/form-data" />
            </label>
        </div>
    </div>
</div>
  

Javascript:

При загрузке изображения вызывается этот jQuery.

 $('#image1').change(function (ev) {
    $("#box_image_2").show();
});

$('#image2').change(function (ev) {
    $("#box_image_3").show();
});

$('#image3').change(function (ev) {
    $("#box_image_4").show();
});

$('#image4').change(function (ev) {
    $("#box_image_5").show();
});
  

Комментарии:

1. покажите свою структуру разметки. Мне кажется странным, что у вас есть image1> box2

2. можете ли вы опубликовать весь код? с помощью html я на самом деле пытаюсь представить, как инициируется изменение

3. Да, вы можете создавать циклы со счетчиками и все такое, но я думаю, что есть более разумный способ с использованием селекторов, в зависимости от вашей разметки.

Ответ №1:

Вы можете использовать data атрибут и множественный селектор. В атрибуте data передайте id элемента, который вы хотите показать, и при изменении получите этот атрибут

 $('#image1,#image2,#image3,#image4').on('change', function(ev) {
  let toShow = $(this).data('show');
  console.log(toShow);
  // $('#' toShow).show();
});  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id='image1' type='checkbox' data-show='box_image_2'>
<input id='image2' type='checkbox' data-show='box_image_3'>
<input id='image3' type='checkbox' data-show='box_image_4'>
<input id='image4' type='checkbox' data-show='box_image_5'>  

Вы также можете использовать селектор подстановочных знаков, где id начинается с image

 $('input[id^="image"]').on('change', function(ev) {
  let toShow = $(this).data('show');
  console.log(toShow);
  // $('#' toShow).show();
});  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id='image1' type='checkbox' data-show='box_image_2'>
<input id='image2' type='checkbox' data-show='box_image_3'>
<input id='image3' type='checkbox' data-show='box_image_4'>
<input id='image4' type='checkbox' data-show='box_image_5'>  

Комментарии:

1. Это работает! Но что, если бы у меня было сто изображений? $(‘#image1,#image2,#image3 … #image100’).on(‘изменить’, функция(ev) {

2. В этом случае используйте общий класс, а в jquery используйте селектор классов

3. И как бы я сделал это с IDS?

4. id всегда уникален. Вы можете использовать селектор подстановочных знаков. Обновленный ответ

Ответ №2:

Вы можете просто использовать классы, подобные этому:

 $('.image').change(function (ev) {
    $(this).next(".box_image").show();
});
  

Ответ №3:

Вы можете попробовать этот метод, используя цикл for.

  • Создайте for цикл
  • Внутри цикла установите для change функции значение image${i} .
  • И внутри change вызова функции show() на box_image_${i 1}

Я также использовал в своем коде шаблонные литералы

 for(let i = 1;i<=4;i  ){
   $(`#image${i}`).change(function (ev) {
      $(`#box_image_${i 1}`).show();
   })
}
  

Комментарии:

1. это отличный ecma 🙂 наслаждайтесь!

2. @brk Нет, нам не нужно iife он прекрасно будет работать без этого. Спасибо за информацию

Ответ №4:

Вставить это в цикл?

 for(var i = 1; i <= 4; i  ){
    $('#image' i).change(function (ev) {
        $("#box_image_" (i 1)).show();
    });

}
  

Комментарии:

1. Возможно, вам понадобится parseInt (), чтобы заставить дополнение работать.

2. вам не хватает a ) — $(«#box_image_» (i 1)).show();

Ответ №5:

Строго на основе вашей разметки и того, как у вас были уникальные идентификаторы для каждого элемента…

Ключ в том, чтобы извлечь это id из родительского контейнера и увеличить на единицу, чтобы показать следующий.

 // Hide all containers except the first, on load (possibly already achieved via CSS)
$("[id^='box_image_']").not(":first").hide();

// Change handler
$("[id^='image']").change(function(ev) {

  // Retreive the index part of the container's id
  var parent_box_image_id = $(this).closest("[id^='box_image_']").attr("id").split("box_image_")[1];
  console.log(parent_box_image_id);
  
  // Increment by one
  parent_box_image_id  ;

  // Show the next one!
  $("#box_image_" parent_box_image_id).show();
});  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="wrapper">
  <div class="box box_image" id="box_image_1">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
          <input type="file" class="image-upload" id="image1" data-show='box_image_2' name="IgniteFormObject.Image1" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_2">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image2" data-show='box_image_3' name="IgniteFormObject.Image2" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_3">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image3" data-show='box_image_4' name="IgniteFormObject.Image3" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_4">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image4" data-show='box_image_5' name="IgniteFormObject.Image4" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" id="box_image_5">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" id="image5" name="IgniteFormObject.Image5" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
</div>  


Но мог бы быть другой способ сделать то же самое более эффективно… Например, полностью забудьте об идентификаторах и классах использования… Взгляните на этот другой фрагмент ниже. 😉

 // Hide all containers except the first, on load (possibly already achieved via CSS)
$(".box_image").not(":first").hide();

// Change handler
$(".image-upload").change(function(ev) {
  $(this).closest(".box_image").next().show();
});  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="wrapper">
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
          <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
  <div class="box box_image" class="box_image">
    <div class="js--image-preview"></div>
    <div class="upload-options">
      <label>
        <input type="file" class="image-upload" name="IgniteFormObject[]" accept="image/*" enctype="multipart/form-data" />
      </label>
    </div>
  </div>
</div>