Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 22.09.2019, 12:09
Аспирант
Отправить личное сообщение для Andrew K Посмотреть профиль Найти все сообщения от Andrew K
 
Регистрация: 15.11.2014
Сообщений: 31

Операции с элементами в JSX в Реакте
Здравствуйте. Делаю проект на Реакте. Появилась задача создать функцию принимающую JSX с какой-то разметкой (например как на первой иллюстрации). Функция должна обернуть детей элемента <section> в условный <aside>, а в элементы <p> поместить компоненты (вторая иллюстрация). Как это можно реализовать?



В стандартном JS операции оборачивания и вставки элементов не вызывают трудностей. Но даже не представляю как это можно реализовать в логике Реакта.

Придумал такой сложный сценарий:

1. Функция принимает не JSX, то строку с разметкой.

2. Строка превращается в HTML-коллекцию в которой дети <section> оборачиваются в условный <aside>.

3. Готовую коллекцию превращаю в объект JavaScript где описаны теги, атрибуты и дети каждого элемента.

4. Объект прогоняется через рекурсивную функцию которая создаёт JSX и по ходу в каждый <p> вставляет компонент Реакта.

Такой сценарий мне не нравится потому что для решения такой простейшей задачи придется написать строчек 300 и подключить пару библиотек.
Ответить с цитированием
  #2 (permalink)  
Старый 22.09.2019, 13:40
Аспирант
Отправить личное сообщение для Andrew K Посмотреть профиль Найти все сообщения от Andrew K
 
Регистрация: 15.11.2014
Сообщений: 31

JSX — это объект где в свойстве props есть массив children. Именно в нем содержатся данные о детях. Но дело в том, что JSX нельзя изменять.

Последний раз редактировалось Andrew K, 22.09.2019 в 17:48.
Ответить с цитированием
  #3 (permalink)  
Старый 23.09.2019, 07:04
Аспирант
Отправить личное сообщение для Andrew K Посмотреть профиль Найти все сообщения от Andrew K
 
Регистрация: 15.11.2014
Сообщений: 31

Понял как нужно делать. Уже созданный JSX изменить нельзя, но можно его обойти и создавать копии элементов. Это делает функция React.cloneElement(). Она принимает элемент для клонирования, объект с его атрибутами и детей. Для создания элемента нужно использовать React.createElement(). Там почти такой же набор параметров: имя тега, его атрибуты и массив детей. Эти две функции решат задачу.
function App() {

    let markup = (
        <section>
            <p /><p />
            <footer />
        </section>
    );


    // Вставляемый компонент
    function Span() { return <span>Span elem</span> }


    // Рекурсивная функция принимает JSX и изменяет разметку.
    function enhanceMarkup(elem) {

        // Если тегом элемента является section, то обернуть его детей в <aside>.
        if(elem.type === 'section') {

            // Составлю массив детей элемента <section>
            let childrenArr = elem.props.children.map((child, i) => {
                return React.cloneElement(
                    // Функция запускается рекурсивно чтобы при следующем запуске обработать <p>
                    enhanceMarkup(child), {key: i}
                );
            });

            // Сделаю новый элемент <aside> куда помещу детей <section>
            let aside = React.createElement('aside', null, childrenArr);

            // Клонирую <section> и поставлю в качестве потомка <aside>
            return React.cloneElement(elem, elem.props, aside)

        }

        // Если тегом элемента является p, то поставить компонент <Span /> потомком
        if(elem.type === 'p') {
            // Клонирую элемент и поставлю компонент как ребёнка
            return React.cloneElement(elem, elem.props, <Span />)
        }

        // Возвратить неизменный elem если его тегом не является section или p (которые обрабатываются и возвращаются в коде выше).
        return elem;
    }


    // Изменить и вернуть новую разметку markup
    return enhanceMarkup(markup)
    
}
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
разное время выполнения операции ropowek Events/DOM/Window 2 08.10.2008 12:27