【速記】ES 6のテンプレート文字列により、Babelプラグインを使用せずに軽量級JSX機能を実現します.


この記事をきっかけに、阮一峰のツイッターが掘削金に転載しているのを見ました. https://juejin.im/pin/5bf6463...
Practの作成者が作成した文字列タグを用いたクラスJSXのライブラリは、ラベルテンプレートの種類JSX文字列をクラスReact.creat Elementまたはh関数に変換することができます. virtual DOMオブジェクトの関数): https://github.com/developit/htm
ES 6文字列の紹介(テンプレート文字列とラベルテンプレートの二節を重点的に読む):http://es6.ruanyifeng.com/#do...
ブラウザレベルAPIは、文字列をDOMオブジェクトに解析します.https://developer.mozilla.org...
元の考えは次の通りです.JSX Quasi-LiteralI've been stugling to get the JSX transpiler playing niely with the tracur compler,specifliallythe flags hidden behind --experimental.
The problem is that the since both the JSX tranpiler and the tracceur compler are parsing the full javascript AST、the y would have to mutally on the sysntax extensions ous:tractually the the atuript cars's async or await keywors、for example、or generator functions.
This prooff-concept is a potenttial solution:instead of using an external JSX tranpiler,we'll parse the faux-xml ourselves,using an ES 6 feature caled quasi-literals.Example
define(function(require) {
    var React   = require('react');
    var jsx     = require('lib/jsxquasi');
    var EchoComponent = React.createClass({
        getInitialState: function() {
            return { value: '' };
        },
        handleChange: function() {
            this.setState({ value: this.refs.input.getDOMNode().value });
        },
        render: function() {
            return jsx`
                
                                       ${this.state.value}                
           `;       }   })    return function() {        var comp = jsx``;        React.renderComponent(comp, document.body);   }; });
A couple of things to notice:
This is valid javascript!Or hamony or es 6 or whatever,but importly,it's not happening out side the js environment.This also allows to use to our standar tooling:the trocur compler knows howtorn jsx Hello; into the equivalent browser comptible es 3、and hence we can use anything the tracceur comple accepts!
This is not exactly the same as JSX according to the spec:it includes quot tes around the atributes,etc.This because this parser is based on DOMParser,and hence needs to be valid XML.It would be straigh forward though to change it it it matched exactly,or to remove the browser dependency(so it could run on the server,eg.)index.js

define(function(require) {

    var React = require('react');
    var paramRegex  = /__(\d)+/;
    var parser      = new DOMParser();
    var errorDoc    = parser.parseFromString('INVALID', 'text/xml');
    var errorNs     = errorDoc.getElementsByTagName("parsererror")[0].namespaceURI;
    // turns the array of string parts into a DOM
    // throws if the result is an invalid XML document.
    function quasiToDom(parts) {
    
        // turn ["
Hi
"]        // into "
Hi
"        var xmlstr = parts.reduce((xmlstr, part, i) => {            xmlstr += part;            if (i != parts.length - 1) { // the last part has no ending param                xmlstr += `__${i}`;           }            return xmlstr;       }, "");       // parse into DOM, check for a parse error       // browser's DOMParser is neat, but error handling is awful       var doc      = parser.parseFromString(xmlstr, 'text/xml');       var errors   = doc.getElementsByTagNameNS(errorNs, 'parsererror');       var error    = '';       if (errors.length > 0) {           error = errors[0].textContent.split('
')[0];           throw `invalid jsx: ${error}
${xmlstr}`;       }       return doc;   }    // turn a document into a tree of react components    // replaces tags, attribute values and text nodes that look like the param    // placeholder we add above, with the values from the parameters array.    function domToReact(node, params) {        var match;                // text node, comment, etc        if (node.nodeValue) {            var value = node.nodeValue.trim();            if (value.length === 0) {                return undefined;           }            match = value.match(paramRegex);            return match ? params[parseInt(match[1])] : value;       }        // node to get react for        // if the node name is a placeholder, assume the param is a component class        var reactNode;        match = node.localName.match(paramRegex)        reactNode = match ? params[parseInt(match[1])] : React.DOM[node.localName];                    // if we don't have a component, give a better error message        if (reactNode === undefined) {            throw `Unknown React component: ${node.localName}, bailing.`;       }        // attributes of the node        var reactAttrs = {};        for (var i = node.attributes.length - 1; i >= 0; i--) {            var attr = node.attributes[i];            reactAttrs[attr.name] = attr.value;            match = attr.value.match(paramRegex);            if (match) {                reactAttrs[attr.name] = params[parseInt(match[1])];           }       }        // recursively turn children into react components        var reactChildren = [];        for (var i = 0; i < node.childNodes.length; i++) {            var child = node.childNodes[i];            var reactChild = domToReact(child, params);            if (reactChild) {                reactChildren.push(reactChild);           }       }        return reactNode(reactAttrs, reactChildren);   }    return function jsx(parts, ...params) {        var doc     = quasiToDom(parts);        var react   = domToReact(doc.firstChild, params);        return react;   } });