Как функционально заполнить HTML JSON

Я пытаюсь понять подход функционального программирования. Насколько я понимаю, это в основном инкапсуляция всего в функции и их передача. Теперь для моего примера я пытаюсь загрузить данные из RESTApi и отобразить их в DOM:

const storyElement = function (): HTMLElement {
    const div = document.createElement('div');
    div.className = 'stories';
    return div;
};

const spinnerElement = function (): HTMLElement {
    const div = document.createElement('div');
    div.className = 'spinner';
    div.innerHTML = `<svg class = "spinner" viewBox = "0 0 100 100" width = "20" height = "20">
                        <circle cx = "50" cy = "50" r = "42" transform = "rotate(-90,50,50)" />
                    </svg>`;
    return div;
};

У меня есть два блока: один для историй и один для значка загрузки. Если содержимое отображается, значок должен исчезнуть.

function getAllStories(callback): void {
    makeRequest(baseUrl(), (res) => spawn(res, callback));
}

function spawn(content, callback): void {
    content = JSON.parse(content);

    if (content instanceof Array === false) {
        content = [content];
    }

    content.forEach(elm =>
        storyElement().innerHTML += `<h1>${elm.title}</h1>
                                     <div class = "story-info">
                                        <i>ID: Post-${elm.id}</i>
                                     </div>
                                     <p>${elm.body}.</p>`
    );
    console.info(content);
    callback();
}

function displayFinished(): void {
    spinnerElement().style.display = 'none';
    document.body.innerHTML += '<div>All done!</div>';
}

Теперь, когда я выполняю getAllStories, консоль выводит результат, но содержимое не отображается в DOM:

document.body.appendChild(storyElement());
document.body.appendChild(spinnerElement());

getAllStories(displayFinished);

Кто-нибудь знает, почему?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Каждый раз, когда вы вызываете storyElement() в своем .forEach, создается новый элемент. Вы никогда не меняли исходный элемент, который вы прикрепили к DOM.

Ответ принят как подходящий

Благодаря @dnt я решил свою проблему. Решение состоит в том, чтобы создать элемент и вложить эту функциональность: получить данные из RESTAPI => создать его в DOM => завершить отображение значка загрузки.

function createElm(className: string, innerHTML?: string): Node {
    const div = document.createElement('div');
    div.className = className;
    if (innerHTML) {
        div.innerHTML = innerHTML;
    }
    document.body.appendChild(div);
    return div;
}

function getAllStories(callback): void {
    makeRequest(baseUrl(), callback);
}

function spawn(content, html, callback): void {
    content = JSON.parse(content);

    if (content instanceof Array === false) {
        content = [content];
    }

    content.forEach(elm =>
        html.innerHTML += `<h1>${elm.title}</h1>
                                     <div class = "story-info">
                                        <i>ID: Post-${elm.id}</i>
                                     </div>
                                     <p>${elm.body}.</p>`
    );

    callback();
}

function displayFinished(html): void {
    html.style.display = 'none';
    document.body.innerHTML += '<div>All done!</div>';
}

const stories = createElm('stories');
const loadingIcon = createElm('spinner', `<svg class = "spinner" viewBox = "0 0 100 100" width = "20" height = "20">
                        <circle cx = "50" cy = "50" r = "42" transform = "rotate(-90,50,50)" />
                    </svg>`);

getAllStories(res =>
    spawn(res, stories, () =>
        displayFinished(loadingIcon)));

Сейчас я просто спрашиваю себя, есть ли лучший вариант для моего подхода. Мне кажется неправильным не использовать простые переменные для dom-элементов ...

Вы не должны изменять DOM в цикле (html.innerHTML += ...), который вызывает перерасчет макета каждый раз. Кроме того, использование такой интерполяции простой строки открывает вам всевозможные неприятные проблемы, такие как недопустимые атаки HTML и XSS. Рекомендую использовать какую-то библиотеку шаблонов.

H.B. 17.12.2018 15:34

Это не реальный проект, просто попробуйте протестировать подход обратного вызова, не хотел заходить так далеко, но спасибо за совет! :)

user10191119 18.12.2018 10:14

Другие вопросы по теме