zoukankan      html  css  js  c++  java
  • React.createElement 与 JSX

    DOM 向JSX的演进

    网页由 DOM 元素构成。React DOM 并不是浏览器的 DOM,而React DOM 只是用来告诉浏览器如何创建 DOM 的方法。通常情况下,我们并不需要 React 就能创建出一个 DOM 元素,但是 React 创建与管理 DOM 的方式有组件化、虚拟 DOM 等更高层次的抽象,由此带来的优势是更快的渲染速度,以及更好的维护性,因此值得去尝试。

    下面分别用 JavaScript 原生方法,React.createElement 方法,以及 JSX 方法来创建一个h1元素,class设置为main,最后挂载在 id 为 root 的 div 元素下面。

    html结构应该如下:

    <div id="root">
      <h1 id="main">Hello React</h1>
    </div>

    1 document.createElement

    JavaScript原生方法,没有过多需要解释的部分。

    // 方法1:document.createElement
    const title = document.createElement('h1');
    title.innerText='Hello React (method 1)';
    title.className='main';
    document.getElementById('root').appendChild(title);

    2 React.creaetElement

    第二种方法是用 React 的 createElement 来创建 React DOM。

    // 方法2:React.createElement
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const title = React.createElement("h1", {className: "main"}, "Hello React (method 2)");
    ReactDOM.render(title, document.getElementById('root'));

    其中 createElement(a, b, c)

    • 第一个参数 a:表示元素的类型,比如:h1, div 等。
    • 第二个参数 b:表示该元素上的属性,使用 JavaScript 对象方式表示。
    • 第三个参数 c:表示该元素内部的内容(子元素),可以是文字,可以继续嵌套另外一个 React.createElement(a, b, c)

    这种方法其实在实际 React 开发中几乎不会使用,因为可以直接 JSX 方法。

    3 JSX

    JSX 是一种 JavaScript 的语法糖。Facebook 开发JSX出来,主要用于 React 中。虽然 JSX 的内容会长得像 html,但还是 JavaScript。

    用 JSX 方法来创建 React DOM 的代码如下:

    // 方法3:JSX
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const title = (
      <h1>Hello React (method 3)</h1>
    );
    
    ReactDOM.render(title, document.getElementById('root'));

    3.1 代码逐行解读:

    第1行: import React from 'react';

    有 JSX 的地方,在文件开头就需要引入 React,因为实际上 JSX 是使用了 React.createElement,JSX 只是一个JS 的语法糖,所以需要引入 React 包,否则会报错。

    第2行: import ReactDOM from 'react-dom';

     react-dom 是一个把React 代码渲染到网页端的包。如果在移动端渲染,就需要使用 React Native 的相关包。 目前(截至2017年12月3日),React 与 ReactDOM 都更新到了 16.0.0,所以在 package.json 中可以看到这两个版本都是最新的版本。

    第4-6行:

    const title = (
      <h1>Hello React (method 3)</h1>
    );

    这就是一段 jsx 代码,实际是 React.createElement 创建一个 React DOM 对象,完全等同于下面这行代码。

    const title = React.createElement("h1", {className: "main"}, "Hello React (method 3)");

    JSX 更加直观,符合我们对 html 结构的认知,如果都用 React.createElement 去创建 React DOM,会非常的繁琐,且容易出错。

    第8行:

    ReactDOM.render(title, document.getElementById('root'));

    把上面创造出来的 React DOM 对象(即虚拟DOM),渲染到网页 id 为 root 的元素中。

    3.2 JSX的限制:标签的包裹

    但是 JSX 有一个限制,就是在 JSX 中 html 代码第一层只能写一个元素。如果有多个标签(元素)并列,形成所谓的相邻JSX元素(adjacement jsx elements),就会报语法错误。通常这种多元素并列的情况,就用在它们外面包裹一层 div。

    (1) 错误的代码

    举例来看,如果 index.js 写成如下代码:

    // 没有 div 包裹会报错
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const title = (
      <h1>Parallel elements demo</h1>
      <p>Content</p>
    );
    
    ReactDOM.render(title, document.getElementById('root'));

    命令行中会报语法错误:相邻 JSX 元素必须用封闭的标签包裹。

    Module build failed: SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag (35:2)
    (2) 正确的代码

    相邻元素 Adjacent JSX elements,在这里其实就是并列的 h1 与 p 标签。所以这里的解决方法就是用一个 div 标签来包裹 h1 与 p 标签。

    // 正确写法:用 div 包裹并列标签
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const title = (
      <div>
        <h1>Parallel elements demo</h1>
        <p>Content</p>
      </div>
    );
    
    ReactDOM.render(title, document.getElementById('root'));

    3.3 突破JSX标签包裹限制

    注意:如果刚接触 React,这部分内容可以跳过后面再来看。

    对于 jsx 外层需要包裹一层 div,如果要突破这个限制,目前有两种方法:

    • 返回数组
    • 使用高阶组件做辅助
    (1) 返回数组

    如果的是数组,就没有问题。

    // 突破JSX标签包裹限制1:返回数组
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const arr = ['Adams', 'Bill', 'Charlie'];
    
    const Arr = () => {
      return arr.map((item, index) => {
        return <p key={index}>{item}</p>
      })
    }
    
    ReactDOM.render(<Arr />, document.getElementById('root'));

    这里是一个数组 arr,包含三个名字,然后用 map 方法得到一个包含三段 JSX 代码的数组。注意这里需要写成匿名函数,然后以 <Arr /> 自封闭标签的格式放入 ReactDOM 的第一个参数位置去渲染。

    当然,这段代码还可以进行简写:

    第一种简写 map 中的剪头函数少了 return

    // 简写1
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const arr = ['Adams', 'Bill', 'Charlie'];
    
    const Arr = () => {
      return arr.map((item, index) => <p key={index}>{item}</p>);
    };
    
    ReactDOM.render(<Arr />, document.getElementById('root'));

    第二种简写是 Arr 这个匿名函数少了 return。

    // 简写2
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const arr = ['Adams', 'Bill', 'Charlie'];
    
    const Arr = () => (arr.map((item, index) => <p key={index}>{item}</p>));
    
    ReactDOM.render(<Arr />, document.getElementById('root'));
    (2) 高阶组件(High Order Component, hoc)

    div 去包裹并列元素的痛点是,我们可能并不需要这个多余的 div 标签,可能会破坏 html 结构,也许上层做了 flex,并不能有效的传递到这些并列标签上。

    所以这里引入了用于辅助的高阶组件 hoc。虽然高阶组件的名字听起来很吓人,然而做的事情很简单,就是传递的作用。

    // 突破JSX标签包裹限制:方法2 高阶组件
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const Aux = props => props.children;
    
    const title = (
      <Aux>
        <h1>Parallel elements demo</h1>
        <p>Content</p>
      </Aux>
    );
    
    ReactDOM.render(title, document.getElementById('root'));

    在上面这段代码中,const Aux = props => props.children; 就是高阶组件。Aux 这个高阶组件的作用是把标签包括的内容进行传递和显示(Aux 是英文中的 auxiliary辅助的)。查看最终 html 结构会发现 div 已经消失了,而且代码没有 div 也能正常。

    高阶组件不仅仅是这里的传递作用,在 Redux 中会大量使用,后面会讲到。

    另外,据称 React 16.2 开始有一个所谓的 fragment 的做法,就是 React 自带了 <Aux></Aux>,但是写成 <></>。在 React 16.2,代码可以写成如下格式:

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const title = (
      <>
        <h1>Parallel elements demo</h1>
        <p>Content</p>
      </>
    );
    
    ReactDOM.render(title, document.getElementById('root'));
  • 相关阅读:
    N in 1 & 多重引导光盘制作
    可启动 ISO 合并、Windows 安装光盘合集
    VS 2005 VC++ 文件类型
    Windows 无人值守安装应答文件详解
    30种下载Youtube视频的方法
    解释YOUTUBE FLV 地址
    Windows下进程通信方式[转]
    进程通讯 DELPHI的类实现
    c#.net常用函数列表
    Javascript, How to make a Dress Up Game (Drag and Drop)
  • 原文地址:https://www.cnblogs.com/gopark/p/11275268.html
Copyright © 2011-2022 走看看