jquery динамическое добавление нескольких изображений во вложенный цикл - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь ввести число в текстовое поле, а затем создать столько экземпляров изображения, которое я выбрал.

В настоящее время он создает только один экземпляр изображения, если я не установил точку останова в инструменте dev. Я думаю, что это может быть связано с async природой javascript.

Я поместил в циклы для проверки счетчик, который возвращает правильное число. Я также попытался сослаться на outerHtml объекта изображения и создать конкатенацию строк для элементов управления, но с этой же проблемой.

var charId = 0;
var count = 0;

$("#character").change(function(e) {
  var amtchar = parseInt($('#amtchar').val());
  if (amtchar < 1) amtchar = 1;

  for (var a = 0; a < amtchar; a++) {
    for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
      var file = e.originalEvent.srcElement.files[i];
      var img = document.createElement("img");
      var reader = new FileReader();
      reader.onloadend = function() {
        img.src = reader.result;
      }
      reader.readAsDataURL(file);
      img.id = 'charImg' + charId;
      $("#character").after(img);
      charId++;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label id='lblchar'>Number of Character</label>
<input id="amtchar" value='0' />
<label id='lblchar'>Add a Character</label>
<input id="character" type="file" />

Ответы [ 3 ]

0 голосов
/ 29 апреля 2020

l oop работает нормально, проблема в области видимости переменной.

Использование var reader = делает эту переменную той же переменной для всей функции .change, поэтому она выглядит так:

$("#character").change(function(e) {
    var reader;

каждый раз через l oop вы обновляете один и тот же считыватель, поэтому в конце l oop есть только один считыватель только с одним .onloadend.

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

let reader =

, которая ограничивает эту переменную внутренней областью (внутри l для 10 * *).

Обновленный фрагмент:

var charId = 0;
var count = 0;

$("#character").change(function(e) {
  var amtchar = parseInt($('#amtchar').val());
  if (amtchar < 1) amtchar = 1;

  for (var a = 0; a < amtchar; a++) {
    for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
      let file = e.originalEvent.srcElement.files[i];
      let img = document.createElement("img");
      let reader = new FileReader();
      reader.onloadend = function() {
        img.src = reader.result;
      }
      reader.readAsDataURL(file);
      img.id = 'charImg' + charId;
      $("#character").after(img);
      charId++;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label id='lblchar'>Number of Character</label>
<input id="amtchar" value='0' />
<label id='lblchar'>Add a Character</label>
<input id="character" type="file" />
0 голосов
/ 29 апреля 2020

В течение для l oop вы постоянно переназначаете img, и каждый раз, когда вызывается onloadend, img будет установлен на последнее изображение в l oop, поскольку l oop будет finni sh до вызова функции , Попробуйте сделать постоянную img и добавить ее в качестве атрибута для читателя. Внутри onloadend вы можете получить доступ к считывателю с помощью этого ключа (код не проверен):

const img = document.createElement("img");
var reader = new FileReader();
reader.img = img;
reader.onloadend = function() {
  this.img.src = this.result;
}
0 голосов
/ 29 апреля 2020

Вы правы, проблема связана с асин c поведением FileReader. Вам нужно закрытие:

var charId = 0;
var count = 0;

$("#character").change(function(e) {
  var amtchar = Math.max(parseInt($('#amtchar').val(), 10), 1);

  for (var a = 0; a < amtchar; a++) {
    for (var i = 0; i < this.files.length; i++) {
      let fileInput = this;
      (function(i) {
        var file = fileInput.files[i];
        var img = document.createElement("img");
        var reader = new FileReader();
        reader.onloadend = function() {
          img.src = reader.result;
        }
        reader.readAsDataURL(file);
        img.id = 'charImg' + charId;
        $("#character").after(img);
        charId++;
      })(i);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label id="lblchar">Number of Character</label>
<input id="amtchar" value="0" />
<label id="lblchar">Add a Character</label>
<input id="character" type="file" />

В качестве альтернативы, если вы можете использовать ES6 в проекте, используйте ключевое слово let вместо:

var charId = 0;
var count = 0;

$("#character").change(function(e) {
  var amtchar = Math.max(parseInt($('#amtchar').val(), 10), 1);

  for (var a = 0; a < amtchar; a++) {
    for (var i = 0; i < this.files.length; i++) {
      let file = this.files[i];
      let img = document.createElement("img");
      let reader = new FileReader();
      reader.onloadend = function() {
        img.src = reader.result;
      }
      reader.readAsDataURL(file);
      img.id = 'charImg' + charId;
      $("#character").after(img);
      charId++;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label id="lblchar">Number of Character</label>
<input id="amtchar" value="0" />
<label id="lblchar">Add a Character</label>
<input id="character" type="file" />

Однако ничего не стоит, что внутренний l oop над коллекцией files является избыточным. Для входного файла не установлен атрибут multiple, поэтому будет только 1 файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...