как создать объект из класса на чистом js

299
17 октября 2021, 11:00

Пытаюсь реализовать функцию добавления картинки на сайт. Для этого был создан класс для картинки:

class Picture_post{ 
  constructor(picture_id, picture_url, likes_count, dislikes_count){ 
    this.picture_id = picture_id; 
    this.picture_url = picture_url; 
    this.likes_count = likes_count; 
    this.dislikes_count = dislikes_count; 
  } 
}

На сайте уже присутствуют дефолтные блоки с картинками, для каждой картинки был созлан вручную объект, например let pic1 = new Picture_post("pic1","url('Img/pic1.png')","3","0"); создан массив var pictures_array = [] и каждый объект был запихнут в этот массив методом pictures_array.push(pic1);. Также была создана коллекция классов let image_block = document.getElementsByClassName("image-block");. Суть в том, что скрипт считает количество блоков с картинками и запихивает их в коллекцию image-block потом он каждому блоку присваивает значения из массива объектов pictures_array

На сайте присутствует форма для загрузки картинки:

<form id="adding-picture-form" method="post"> 
  <button id="submit-picture-uploading-button" type="button" name="submit-picture-uploading-button"></button> 
  <label id="adding-picture-label" for="adding-picture-input">Add your Picture</label> 
  <input id="adding-picture-input" name="adding-picture-input" type="file" accept="image/*"> 
</form>

Сам input был скрыт от глаз юзера, а открытие диалогового (для загрузки картинки) окна происходит через клик на label. На данный момент на форме висят такие функции:

let adding_picture_label = document.getElementById("adding-picture-label"); 
let adding_picture_input = document.getElementById("adding-picture-input"); 
let submit_picture_uploading_button = document.getElementById("submit-picture-uploading-button"); 
 
adding_picture_input.addEventListener('change',()=>{ 
   let picture = adding_picture_input.files[0]; 
   if(picture){ 
     adding_picture_label.innerHTML = picture.name; 
     return picture; 
   } 
   else{ 
     adding_picture_label.innerHTML = 'Add your Picture'; 
     return picture; 
   } 
 },false); 
 
submit_picture_uploading_button.addEventListener('click', function () { 
  let picture = adding_picture_input.files[0]; 
   if(picture){ 
     console.log(picture); 
   } 
   else{ 
     adding_picture_label.innerHTML = 'Upload picture first'; 
   } 
  },false);

Мне бы хотелось, чтобы при клике на кнопку submit скрипт создавал новый объект картинки из моего класса, picture_url присваивал значение adding_picture_input.files[0] likes_count и dislikes_count было по нулям. Проблема в том, что я не знаю каким образом сделать создание нового объекта "универсальным". Что бы можно было прописать что-то типо let pic[pictures_array.length] = new Picture_post("pic"[pictures_array.length],"url('Img/adding_picture_input.files[0]')","0","0"); где место переменной pictures_array.length прописывалась уже готовенькая циферка и на выходе получалось, к примеру let pic8 = new Picture_post("pic8","url('Img/pic8.png')","0","0"); и это добро сохранялось в массиве pictures_array для дальнейшей работы. Благодарю за любую помощь.

Answer 1

Зачем Вам переменные pic1, pic2 и так далее?

var pictures_array = [];
...
var i = pictures_array.length;
...
i++;
pictures_array.push(new Picture_post("pic" + i, "url('Img/pic" + i + ".png')", 0, 0); 
Answer 2

Ключевые моменты:

  1. Класс без методов и приватных свойств - имеет смысл только если расширять им стандартный DOM-объект (показано в примере). В остальных случаях, для хранения инфы в виде "ключ: значение", будет достаточно простого объекта;
  2. Расширяются не только объекты через "наследование", но и их экземпляры. Добавление свойств экземпляру DOM-объекта (элементу) это абсолютно нормальная практика, несмотря на то что некоторые ее боятся. Главное - не допускать возможного пересечения имен свойств (в примере используется объектное свойство, структурное хранение это один из вариантов избежания конфликтов);
  3. При наличии живой коллекции (от getElementsByClassName), массив элементов/экземпляров совершенно не нужен - см. в примере код обновления общего количества картинок. Коллекция обновляется автоматически, поэтому и называется живой. А так как мы расширяем свойствами объекты элементов - всегда можем получить доступ к этим свойствам через коллекцию (например, лайки первого изображения это imgs[0].myOpts.cntLikes)

class MyImg extends Image { 
  constructor(opts = {}) { 
    super();  
    const { src, classes, ...myOpts } = opts;  
    Object.assign(this, { myOpts });  
    this.addEventListener('load',  
      ({ target }) => URL.revokeObjectURL(target.src) 
    , { once: true });  
    this.classList.add(...classes);  
    this.src = src;  
  } 
} 
 
const imgs = document.getElementsByClassName('my-class'),  
      glry = document.querySelector('#gallery'),  
      frm  = document.forms.addPic; 
frm.picFile.addEventListener('change', ({ target }) => { 
  if (!target.files.length) return;  
  glry.appendChild(new MyImg({ 
    src: URL.createObjectURL(target.files[0]),  
    classes: ['my-class'],  
    cntLikes: 0, 
    cntDislikes: 0 
  }));  
  frm.querySelector('.pic-count').textContent = imgs.length;  
  frm.reset();  
});
body { font-family: sans-serif; } 
#gallery { display: flex; flex-flow: row wrap; align-items: center; } 
#gallery .my-class { max-width: 100%; width: 200px; margin: 0 auto 0.5rem auto; } 
#add-pic, #add-pic label { display: block; width: 100%; padding: 0.3em 0 0.5em 0; text-align: center; } 
#add-pic .choose-file { text-decoration: underline dashed; color: #47e; background: #eee; } 
#add-pic input[type="file"] { display: none; }
<div id="gallery"></div> 
<form id="add-pic" name="addPic" action="javascript:void(0)"> 
  <label>Total: <span class="pic-count">0</span> picture(s)</label> 
  <label class="choose-file">Add your Picture 
    <input name="picFile" type="file" accept="image/*"> 
  </label> 
</form>

Возможность ставить лайки/дизлайки, их вывод в галерее, и работа с localStorage - не реализованы сознательно, чтобы оставить пространство для доработки решения (т.к. задание учебное, а копипаст ничему не научит). При возникновении трудностей с реализацией этих фич, всегда можно задать новый, более конкретный вопрос :)

READ ALSO
Редирект в приложение Android/IOS

Редирект в приложение Android/IOS

У меня есть сайтНа нем необходимо сделать редирект в приложение Instagram

152
Обмен данными между программами

Обмен данными между программами

Есть программа на С# (MonoDevelop, Linux), которая может при запуске управлять демоном (старт/стоп/статус)Как можно осуществить передачу данных между...

151