jsx(6)-本质和原理

2022-11-09  本文已影响0人  未路过
image.png

babel每遇到一个标签(div,span之类的html标签,或者是组件名字<App/>),就会将里面它转换成React.createElement()这个函数的调用。

image.png

React.createElement("div", {className: "header"}, React.createElement(...))创建出来的对象,就是虚拟dom。
然后再根据虚拟dom,生成真实dom。

      // 1.定义App根组件
      class App extends React.Component {
        constructor() {
          super();
          this.state = {
            message: "Hello World",
          };
        }

        render() {
          const { message } = this.state;

          return (
            <div>
              <div className="header">Header</div>
              <div className="Content">
                <div>{message}</div>
                <ul>
                  <li>列表数据1</li>
                  <li>列表数据2</li>
                  <li>列表数据3</li>
                  <li>列表数据4</li>
                  <li>列表数据5</li>
                </ul>
              </div>
              <div className="footer">Footer</div>
            </div>
          );
        }
      }

      // 2.创建root并且渲染App组件
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App />);
"use strict";

// 1.定义App根组件
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      message: "Hello World"
    };
  }
  render() {
    const { message } = this.state;
    return /*#__PURE__*/ React.createElement(
      "div",
      null,
      /*#__PURE__*/ React.createElement(
        "div",
        {
          className: "header"
        },
        "Header"
      ),
      /*#__PURE__*/ React.createElement(
        "div",
        {
          className: "Content"
        },
        /*#__PURE__*/ React.createElement("div", null, message),
        /*#__PURE__*/ React.createElement(
          "ul",
          null,
          /*#__PURE__*/ React.createElement(
            "li",
            null,
            "\u5217\u8868\u6570\u636E1"
          ),
          /*#__PURE__*/ React.createElement(
            "li",
            null,
            "\u5217\u8868\u6570\u636E2"
          ),
          /*#__PURE__*/ React.createElement(
            "li",
            null,
            "\u5217\u8868\u6570\u636E3"
          ),
          /*#__PURE__*/ React.createElement(
            "li",
            null,
            "\u5217\u8868\u6570\u636E4"
          ),
          /*#__PURE__*/ React.createElement(
            "li",
            null,
            "\u5217\u8868\u6570\u636E5"
          )
        )
      ),
      /*#__PURE__*/ React.createElement(
        "div",
        {
          className: "footer"
        },
        "Footer"
      )
    );
  }
}

// 2.创建root并且渲染App组件
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(/*#__PURE__*/ React.createElement(App, null));

React.createElement(component, props, ...children)
这个children也是React.createElement()。
逗号分开。
/#PURE/
babel告诉你这个函数是纯函数调用。可以在webpack的tree-shaking里面被摇掉。不用的话,这个函数将不会被打包

jsx本质,将标签转换成Reac.createElement()函数。

Reac.createElement()函数创建出来的是ReactElement对象

虚拟dom的创建原理

image.png
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>计数器</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="../lib/react.js"></script>
    <script src="../lib/react-dom.js"></script>

    <script>
      // 1.定义App根组件
      class App extends React.Component {
        constructor() {
          super();
          this.state = {
            message: "Hello World",
          };
        }

        render() {
          const { message } = this.state;
          const element = React.createElement(
            "div",
            null,
            /*#__PURE__*/ React.createElement(
              "div",
              {
                className: "header",
              },
              "Header"
            ),
            /*#__PURE__*/ React.createElement(
              "div",
              {
                className: "Content",
              },
              /*#__PURE__*/ React.createElement("div", null, message),
              /*#__PURE__*/ React.createElement(
                "ul",
                null,
                /*#__PURE__*/ React.createElement(
                  "li",
                  null,
                  "\u5217\u8868\u6570\u636E1"
                ),
                /*#__PURE__*/ React.createElement(
                  "li",
                  null,
                  "\u5217\u8868\u6570\u636E2"
                ),
                /*#__PURE__*/ React.createElement(
                  "li",
                  null,
                  "\u5217\u8868\u6570\u636E3"
                ),
                /*#__PURE__*/ React.createElement(
                  "li",
                  null,
                  "\u5217\u8868\u6570\u636E4"
                ),
                /*#__PURE__*/ React.createElement(
                  "li",
                  null,
                  "\u5217\u8868\u6570\u636E5"
                )
              )
            ),
            /*#__PURE__*/ React.createElement(
              "div",
              {
                className: "footer",
              },
              "Footer"
            )
          );
          console.log(element);

          return element;
        }
      }

      // 2.创建root并且渲染App组件
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(React.createElement(App, null));
    </script>
  </body>
</html>

image.png

原因是React利用ReactElement对象组成了一个JavaScript的对象树;(reactElement对象, 这个对象有props属性,里面存放着children的reatElement对象,是树结构)
 JavaScript的对象树就是虚拟DOM(Virtual DOM);

虚拟dom转换成真实dom

babel将标签转换成react.createElement的函数调用。然后浏览器执行的时候,会得到react Element对象,也就是js对象。这些js对象,经过渲染,就会变成真实dom。

vue的化里面的template里面有很多指令,v-for,v-bind之类的也得解析,react中的解析更见简单明了,而且vue的template是vue自己解析的。react的jsx是babel解析的。

虚拟dom的作用(面试题)

1.没有必要重新渲染所有的真实dom。
在虚拟dom里面快速进行diff算法,来决定到底哪些东西更新,哪些东西不更新。(虚拟dom比较简单,真实的dom有很多方法之类的,很占内存空间。)
2.可以做跨平台应用程序。
虚拟dom的本质是js对象。react可以将虚拟dom渲染成真实dom。也是通过document.createElement方法渲染到web的dom上面的。ratct里面有个技术叫做react native,它可以渲染成ios,安卓上面的控件,用react开发原生的东西。


image.png

声明式编程

image.png

我们最主要是在做的事情是在维护这个状态,你只需要告诉我你希望界面长什么样子,然后维护着你这里这个状态就可以了.然后呢,当状态发生改变的时候,你调这个setState,告诉我状态发生改变了,我重新渲染,那么真实的到底它的DOM如何更新,不需要你来做。

在react中是没有数据劫持的,是需要手动调用setState函数更新界面。vue中有数据劫持,当数据改变的时候,自动渲染页面。

上一篇下一篇

猜你喜欢

热点阅读