Babel Standalone работает с динамически добавляемым JSX-кодом, когда Babel Standalone предоставляется как атрибут SRC тега SCRIPT. Он не работает, когда он добавляется к DOM с помощью JavaScript. Это неверно для библиотек React, которые отлично работают с динамически добавляемым JSX, когда библиотеки React добавляются динамически.

Во-первых, вот файл JSX (response.jsx):

class HelloMessage extends React.Component {
  render() {
    return <h1>Hello</h1>;
  }
}
ReactDOM.render(<HelloMessage/>, document.getElementById('app'));

Затем вот HTML, который его использует. Обратите внимание, что библиотеки React и файл JSX добавляются динамически; это работает правильно. Однако Babel Standalone переносит JSX только тогда, когда Babel Standalone добавляется в качестве SRC элемента SCRIPT, а не когда он добавляется с использованием того же JavaScript, что и остальная часть JS / JSX. Переключайтесь между двумя состояниями, перезагружая один вызов Babel Standalone и удаляя другой. Я хочу динамически добавить Babel Standalone ... в чем проблема?

<!doctype html>
<html>
<head>
    <title>Inscrutable Babel Problem</title>
</head>
<body>
    <div>
        <p>Babel works only when added as a src of a SCRIPT element; it fails when the script is appended dynamically. HELLO will display below when it works.</p>
    </div>
    <div id=app></div>
<script>
function loadScript(src, type) {
    var script = document.createElement('script');
    script.src = src;
    if (type) {
        script.type = type;
    }
    script.async = false;
    document.body.appendChild(script);
}
loadScript('https://unpkg.com/react@16/umd/react.production.min.js');
loadScript('https://unpkg.com/react-dom@16/umd/react-dom.production.min.js');

// You'll need to place the REACT.JSX code above in a locally hosted file to reproduce the results: 
loadScript('react.jsx', 'text/babel');

// To toggle: rem the following line and un-rem the corresponding SCRIPT tag below
loadScript('https://unpkg.com/babel-standalone@6/babel.min.js');

</script>

<!-- To toggle: un-rem the the following SCRIPT tag and rem the last loadScript() call in the JavaScript above -->
<!--
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
-->

</body>
</html>
0
Tom 5 Дек 2018 в 20:14

1 ответ

Лучший ответ

Babel-standalone ожидает срабатывания события DOMContentLoaded, что приводит к добавлению перенесенной версии любых блоков сценария JSX в HEAD. В конце загрузки DOM, если HEAD не имеет SCRIPT, снова запустить событие DOMContentLoaded; ниже приведен блок кода, который делает трюк.

NB: это исправление kludge, специфичное для автономной версии babel; если любая другая используемая библиотека также отвечает на DOMContentLoaded, ее код может выполняться второй раз, что может быть нежелательно.

document.onreadystatechange = function () {
    if (document.readyState === 'complete') {
        if (document.querySelectorAll('head script').length === 0) {
            window.dispatchEvent(new Event('DOMContentLoaded'));
        }
    }
}

Таким образом, полный код, отредактированный для работы выше:

<!doctype html>
<html>
<head>
    <title>Inscrutable Babel Problem</title>
    <meta charset="utf-8">
</head>
<body>
    <div>
        <p>Babel runs when the DOMContentLoaded event is fired. HELLO will display below when it works.</p>
    </div>
    <div id=app></div>
<script>
function loadScript(src, type) {
    var script = document.createElement('script');
    script.src = src;
    if (type) {
            script.type = type;
    }
    script.async = false;
    document.body.appendChild(script);
}
loadScript('https://unpkg.com/react@16/umd/react.production.min.js');
loadScript('https://unpkg.com/react-dom@16/umd/react-dom.production.min.js');
loadScript('javascript/react.jsx', 'text/babel');
loadScript('https://unpkg.com/babel-standalone@6/babel.min.js');

// Listen for completion of DOM loading; if no SCRIPT element has been added
// to the HEAD, fire the DOMContentLoaded event again:
document.onreadystatechange = function () {
    if (document.readyState === 'complete') {
        if (document.querySelectorAll('head script').length === 0) {
            window.dispatchEvent(new Event('DOMContentLoaded'));
        }
    }
}

</script>
</body>
</html>
1
Tom 8 Дек 2018 в 16:17