Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Как лучше формировать DOM по данным массива? (https://javascript.ru/forum/dom-window/65959-kak-luchshe-formirovat-dom-po-dannym-massiva.html)

Bravo 17.11.2016 17:22

Как лучше формировать DOM по данным массива?
 
Приветствую :thanks: , возник такой вопрос. Есть след. данные:
"car": [
    {
      "id": 1,
      "name": "BMW",
      "year": 1999,
      "parts": [1,2]
    }],
  "parts": [
    {
      "id": 1,
      "name": "engine"
    },
    {
      "id": 2,
      "name": "window"
    }
]

Это короткий вариант, полный содержит ~100 деталей.

Моя задача сформировать из этого страницу, где будут отображаться список из ~100 деталей (parts) и показано для какой это машины (car.name).

<div id="parts">
<div>Part 1 (engine) – BMW</div>
<div>Part 2 (window) – BMW</div>
</div>


Страница формируется в реальном времени, после получения данных, следовательно в начале элемент #parts пустой.

Как лучше перебирать и сопоставлять данные массива и формировать DOM, чтобы это было не слишком медленно? Интересует красивый и понятный вариант на чистом JS и возможные варианты на Jquery.

Coriolan161 17.11.2016 17:40

Bravo,
надо пихать в DocumentFragment заджойненный массив твоих партов, а потом добавлять твой DocumentFragment в parts

Coriolan161 17.11.2016 17:41

Bravo,
никакой херни с createElement в цикле

Rise 17.11.2016 17:49

Coriolan161, у DocumentFragment нет innerHTML и insertAdjacentHTML

Coriolan161 17.11.2016 18:09

Bravo,
Отставить. Идеи смешались.
1) Либо пихать заджойненный массив в #parts.innerHTML
2) Либо создавать DocumentFragment, обходить все парты в цикле, делать createElement('div'), в див пихать детали и фрагмент.appendChild(див), и в конце запихать фрагмент в #parts

Dilettante_Pro 17.11.2016 18:18

только данные немного поправил
<!DOCTYPE html>
<html>
<head>
    <title>Cars Details</title>
    <script>
        var cars = [
    { "car":
     {
        "id": 1,
        "name": "BMW",
        "year": 1999
    },
        "parts": [
    {
        "id": 11,
        "name": "engine"
    },
    {
        "id": 12,
        "name": "window"
    }]
    },
    { "car":
    {
        "id": 2,
        "name": "Audi",
        "year": 2000
    },
        "parts": [
    {
        "id": 21,
        "name": "engine"
    },
    {
        "id": 22,
        "name": "window"
    }]
    }
];
    window.onload = function () {
        var fragment = document.createDocumentFragment();
        cars.forEach(function (item, i, arr) {
            item.parts.forEach(function (part, j, ar) {
                var d = document.createElement('div');
                d.setAttribute('id', part.id);
                fragment.appendChild(d);
                d.innerHTML = 'Part ' + part.id + ' (' +part.name + ') ' + item.car.name ;
            });
        });
        parts.appendChild(fragment);
    }

    </script>
</head>
<body>
   <div id="parts"></div>
</body>
</html>

Цитата:

В современных браузерах эффект от такой оптимизации может быть различным, а на небольших документах иногда и отрицательным.
https://learn.javascript.ru/multi-insert

рони 17.11.2016 18:42

:write:
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">


</head>

<body>
<div id="parts"></div>
 <script>
var data = {
"car": [
    {
      "id": 1,
      "name": "BMW",
      "year": 1999,
      "parts": [1,2]
    }],
  "parts": [
    {
      "id": 1,
      "name": "engine"
    },
    {
      "id": 2,
      "name": "window"
    }
] };

var parts = data.parts.reduce(function(a, b) {
        a[b.id] = b.name;
        return a
    }, {}),
    arr = data.car.reduce(function(a, b) {
        return a.concat(b.parts.map(function(a) {
            return "Part " + a + " (" + parts[a] + ") - " + b.name
        }))
    }, []);
 document.querySelector('#parts').insertAdjacentHTML("beforeEnd", "<div>" + arr.join("</div><div>") +"</div>");

  </script>
</body>
</html>

рони 17.11.2016 18:47

Dilettante_Pro,
исравил beforeEnd


Часовой пояс GMT +3, время: 16:22.