Вызов внешней JS-функции в React-приложении

190
23 декабря 2021, 01:40

Есть приложение на реакте, мне с бэкенда через ajax приходит сгенерированная там js функция для сторонней библиотеки. Проблема в том, что эта функция не отрабатывает. Для тестирования максимально упростил код:

HTML:

<div id="roor"></div> 
<div id="external_module"></div>

React:

                axios.request({ 
                    method: 'post', 
                    url: '/_ajax/handler.php', 
                    dataType: 'json', 
                    headers: { 
                        'X-Requested-With': 'XMLHttpRequest', 
                        'Content-Type': 'application/x-www-form-urlencoded' 
                    }, 
                    data:qs.stringify(any_data) 
                }) 
                .then((param) => { 
                        document.querySelector('#external_module').innerHTML = param.data.content; 
                });

и возвращаемый JS:

<button id=\"clickButton\">Клик</button> 
        <script type=\"text/javascript\"> 
            var clickHandler = function (e) { 
              console.log('adsfnjdfaskjfas'); 
            }; 
            $('#clickButton').on('click', clickHandler); 
        </script>

Как заставить возвращаемый JS работать?

Answer 1

При инъекции скрипта с кодом между тегами, этот код не будет выполнен, из соображений безопасности.
Это не касается программно добавляемых скриптов с атрибутом src.
(хотя на последние конечно действуют ограничения CSP, но это уже другая история)

Тем не менее, код в текстовом виде можно выполнить без инъекции - либо через eval, либо с помощью такой магии вуду:

const dest = document.querySelector('#external_module'),  
      re = /<script[^>]*>([\s\S]+?)<\/script>/gi;  
let code = [];  
dest.innerHTML = getContent().replace(re, (m, c) => (code.push(c), ''));  
code = code.filter(c => void (new Function(c))());  
 
function getContent() {  // вместо AJAX 
  return `<button id=\"clickButton\">Клик</button> 
    <script type=\"text/javascript\"> 
      var clickHandler = function (e) { 
        console.log('Работает!'); 
      }; 
      $('#clickButton').on('click', clickHandler); 
    <\/script>`;  // здесь '\' только для того чтобы сниппет не ломался 
}
<div id="external_module"></div> 
<script src="https://unpkg.com/jquery/dist/jquery.min.js"></script>

Ну и простая инъекция, для демонстрации того что она действительно не дает результата:

document.querySelector('#external_module').innerHTML = getContent(); 
 
function getContent() { 
  return `<button id=\"clickButton\">Клик</button> 
    <script type=\"text/javascript\"> 
      var clickHandler = function (e) { 
        console.log('adsfnjdfaskjfas'); 
      }; 
      $('#clickButton').on('click', clickHandler); 
    <\/script>`;  
}
<div id="external_module"></div> 
<script src="https://unpkg.com/jquery/dist/jquery.min.js"></script>

READ ALSO
Анализ временных рядов нейросетью

Анализ временных рядов нейросетью

Способна ли библиотека решить следующую задачу (вычислительную задачу)?

236
Фильтрация массива с помощью map [дубликат]

Фильтрация массива с помощью map [дубликат]

Кажется, я не до конца понимаю,как работает mapЯ пытаюсь вернуть массив,который не содержит элемента с определенным id

156
Модальные окна и динамические списки

Модальные окна и динамические списки

Надо сделать подобноеЯ подобное сделал, но это получается говнокод какой-то и обслуживать его тоже вредно

191
Разделить API config на версию dev и prod webpack

Разделить API config на версию dev и prod webpack

Подскажите пожалуйста, есть вот файл configjs в нем экспортируемая переменная с ссылкой на API, но есть API для dev версии, а есть отдельное API для prod версии,...

304