JSX详解

作者: ThisWu | 来源:发表于2021-01-05 10:02 被阅读0次

    原文地址:
    https://jasonformat.com/wtf-is-jsx/

    JSX实际上非常简单:花1分钟阅读一下,您将了解到有关模板的有趣替代方法的所有知识。

    替代标题:“与JSX一起生活”

    语用

    您可以声明每个文件或每个函数的名称,以告知您的编译器(例如Babel)在运行时应为每个节点调用的函数的名称(请参见Transpilation)。

    在下面的示例中,我们说的是“h()为每个节点注入对函数的调用”:

    /** @jsx h */
    
    

    转译

    如果您还没有使用转译器,应该使用。使用ES6 / ES2015时,编写,调试,测试和运行JavaScript更加有效。Babel是那里最受欢迎和推荐的转译器,所以我认为这就是您所使用的。

    除了将您的ES6 / ES7 +语法转换为当今的JavaScript之外,Babel还包括对JSX的编译支持 <mark style="background: rgb(253, 255, 182); color: rgb(0, 0, 0);">开箱即用</mark>。您无需添加或更改任何内容即可使用此功能。

    通过看一个非常简单的示例,最容易看出它是如何工作的:

    之前:( 您编写的代码)

    /** @jsx h */
    let foo = <div id="foo">Hello!</div>;  
    
    

    之后:( 您运行的代码)

    var foo = h('div', {id:"foo"}, 'Hello!');  
    
    

    您可能正在看第二个代码片段,以为使用功能构建UI并不会太糟糕...

    这就是为什么我开始加入JSX的原因:如果它从地球上消失了,用手编写输出仍然会很舒适。

    JSX只是已经相当不错的语法的糖。**

    人们甚至将其用于整个项目:超标


    让我们构建一个JSX渲染器

    首先,我们需要定义h()转译代码正在调用的函数。

    您可以随心所欲地调用它,h()因为这种类型的“构建器”功能的原始想法被称为hyperscript(“文本“ +”爪哇脚本”)。

    function h(nodeName, attributes, ...args) {  
          let children = args.length ? [].concat(...args) : null;
          return { nodeName, attributes, children };
    }
    
    

    好的,那很容易。

    不熟悉ES6 / ES2015?

    • ...在参数列表是一个休息PARAM。它将参数的“其余”收集到一个数组中。
    • concat(...args)位是一个散布运算符:它采用该Array并将其扩展为concat()。的参数。concat()这里的用途是折叠子节点的任何嵌套数组。

    现在我们有了这些嵌套的JSON对象,我们的h()函数就会退出,因此我们最终得到了像这样的“树”:

    {
      nodeName: "div",
      attributes: {
        "id": "foo"
      },
      children: ["Hello!"]
    }
    
    

    因此,我们只需要一个接受该格式并吐出实际DOM节点的函数:

    function render(vnode) {  
        // Strings just convert to #text Nodes:
        if (vnode.split) return document.createTextNode(vnode);
    
        // create a DOM element with the nodeName of our VDOM element:
        let n = document.createElement(vnode.nodeName);
    
        // copy attributes onto the new node:
        let a = vnode.attributes || {};
        Object.keys(a).forEach( k => n.setAttribute(k, a[k]) );
    
        // render (build) and then append child nodes:
        (vnode.children || []).forEach( c => n.appendChild(render(c)) );
    
        return n;
    }
    
    

    甜。不难理解它是如何工作的。
    如果有帮助,您可以将“虚拟DOM”视为如何构建给定DOM结构的非常简单的配置。

    虚拟DOM的好处是它非常轻巧。小对象是指其他小对象,由易于优化的应用程序逻辑组成的结构。

    这也意味着它不依赖于任何渲染逻辑或慢速DOM方法。


    使用JSX

    我们知道JSX已转换为h()函数调用。
    这些函数调用将创建一个简单的“虚拟” DOM树。
    我们可以使用该render()函数制作匹配的“真实” DOM树。
    看起来像这样:

    // JSX -> VDOM:
    let vdom = <div id="foo">Hello!</div>;
    
    // VDOM -> DOM:
    let dom = render(vdom);
    
    // add the tree to <body>:
    document.body.appendChild(dom);  
    
    
    局部,迭代与逻辑:无新语法

    除了使用模板语言引入的有限概念之外,我们还提供了所有JavaScript。

    “部分”是无逻辑/有限逻辑模板引擎引入的概念,用于跨不同上下文重用视图的块。

    迭代是每种新的模板语言似乎都重新发明的东西(我和任何人一样内)。使用JSX,无需学习一次性语法:迭代JavaScript程序中的其他位置。你选择的迭代风格,最适合给定任务:[].forEach()[].map()forwhile循环等

    逻辑就像迭代一样,是模板语言喜欢重新发明的东西。一方面,无逻辑模板提供了将逻辑嵌入到视图中的非常差的方法:有限的构造(例如{{#if value}}将逻辑推送到控制器层中),令人肿。这样可以避免构建用于描述更复杂逻辑的语言,从而避免了可预测性和安全性陷阱。

    另一方面,使用代码生成的引擎(从粗略到不可原谅的技术范围)通常拥有执行任意JavaScript表达式以进行逻辑甚至迭代的能力。这是一个不惜一切代价避免这种情况的充分理由:您的代码被从其原始位置(可能是模块,闭包或标记内)中剥离出来,并在“其他位置”进行了评估。这对我来说是无法预料或不够安全的。

    JSX允许使用JavaScript的所有语言功能,而无需在构建步骤中以及在没有eval()&朋友的情况下依赖于生成怪诞的代码。

    // Array of strings we want to show in a list:
    let items = ['foo', 'bar', 'baz'];
    
    // creates one list item given some text:
    function item(text) {  
        return <li>{text}</li>;
    }
    
    // a "view" with "iteration" and "a partial":
    let list = render(  
      <ul>
        { items.map(item) }
      </ul>
    );
    
    

    render()返回DOM节点(<ul>在上述情况下为),因此我们只需要将其放入DOM中即可:

    document.body.appendChild(list);  
    
    

    把它放在一起

    这是小型虚拟DOM渲染器的完整资源以及使用它的视图。
    下面提供带有某些样式的CodePen。

    const ITEMS = 'hello there people'.split(' ');
    
    // turn an Array into list items: 
    let list = items => items.map( p => <li> {p} </li> );
    
    // view with a call out ("partial") to generate a list from an Array:
    let vdom = (  
        <div id="foo">
            <p>Look, a simple JSX DOM renderer!</p>
            <ul>{ list(ITEMS) }</ul>
        </div>
    );
    
    // render() converts our "virtual DOM" (see below) to a real DOM tree:
    let dom = render(vdom);
    
    // append the new nodes somewhere:
    document.body.appendChild(dom);
    
    // Remember that "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties.
    let json = JSON.stringify(vdom, null, '  ');
    
    // The whole process (JSX -> VDOM -> DOM) in one step:
    document.body.appendChild(  
        render( <pre id="vdom">{ json }</pre> )
    );
    

    相关文章

      网友评论

          本文标题:JSX详解

          本文链接:https://www.haomeiwen.com/subject/udjioktx.html