当动态附加Babel时,Babel Standalone不会翻译动态附加的JSX

时间:2018-12-05 17:14:26

标签: javascript reactjs jsx babel react-dom

当Babel Standalone作为SCRIPT标签的SRC属性提供时,Babel Standalone可以动态添加JSX代码。使用JavaScript将其附加到DOM时,它不起作用。对于React库而言,情况并非如此,当动态添加React库时,它可以与动态附加的JSX一起正常工作。

首先,这是JSX文件(react.jsx):

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

接下来,这是使用它的HTML。注意,React库和JSX文件是动态添加的;这正常工作。但是,Babel Standalone仅在将Babel Standalone添加为SCRIPT元素的SRC时才转译JSX,而不是在使用与添加JS / JSX其余部分相同的JavaScript进行添加时,才转译JSX。通过取消对一个Babel Standalone调用的重发和取消对另一个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>

1 个答案:

答案 0 :(得分:0)

babel-standalone监听触发的DOMContentLoaded事件,这会导致它向HEAD附加任何JSX脚本块的转译版本。在DOM加载结束时,如果HEAD没有SCRIPT,则再次触发DOMContentLoaded事件;下面是完成此操作的代码块。

NB:这是专门针对babel-standalone的kludge修复程序;如果正在使用的任何其他库也响应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>