george-es / Blog

My Blog
0 stars 0 forks source link

JSX 原理 #75

Open george-es opened 3 years ago

george-es commented 3 years ago

首先思考一个问题,如何用 JS 对象来表现一个 DOM 元素的结构

<div className="content" id="box">
    <h1>Hello World</h1>
</div>

其实每个 DOM 都可以用 JS 对象来表示,一个 DOM 元素包含的信息只有 3 个 —— 标签名,属性,子元素

{
    tag: 'div',
    attrs: { className: 'content', id: 'box'},
    children: [{
        tag: 'h1',
        attrs: null,
        children: ['Hello World']
    }]
}

也就是说任何 HTML 表示的 UI 信息都可以通过 JS 对象来描述。但是在开发中,用 JS 描述太长了,结构也不是很清晰,还是用 HTML 的方式写比较方便。

于是 React 就把 JS 的语法扩展了一下,让 JS 语言能够支持这种直接在 JS 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便多了,通过 babel 编译时,会把类似 HTML 的 JSX 结构转换成 JS 的对象结构。

image

React.createElement 会构建一个 JS 对象来描述你 HTML 结构的信息,包括标签,属性,还有子元素等。所以使用 React 和 JSX 时候一定要经过 babel 编译。

也就是说JSX 其实就是 JS 对象

有了表示 HTML 结构和信息的对象以后,就可以拿去构造真正的 DOM 元素,然后把这个 DOM 元素塞到页面上,这就是 ReactDOM.render 所干的事情。ReactDOM.render 功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上

总结一下从 JSX 到页面到底经过了什么样的过程:

image

为什么不直接从 JSX 直接渲染构造 DOM 呢需要经过中级这一层?

一、当我们拿到一个表示 UI 的结构和信息的对象以后,不一定会把元素渲染到浏览器的普通页面上,我们有可能把这个结构渲染到 canvas 上,或者是手机 App 上。所以这也是为什么会要把 react-dom 单独抽离出来的原因,可以想象有一个叫 react-canvas 可以帮我们把 UI 渲染到 canvas 上,或者是有一个叫 react-app 可以帮我们把它转换成原生的 App(实际上这玩意叫 ReactNative)。

二、有了这样一个对象。当数据变化,需要更新组件的时候,就可以用比较快的算法操作这个 JavaScript 对象,而不用直接操作页面上的 DOM,这样可以尽量少的减少浏览器重排,极大地优化性能。

所以 ① JSX 是 JS 语言的一种语法扩展,长的像 HTML 但不是 HTML ② React 可以用 JSX 来描述组件长什么样。 ③ JSX 在编译的时候会变成相应的 JS 对象描述。 ④ react-dom 负责把这个描述 UI 信息的 js 对象变成 DOM 元素,并渲染到页面上。

george-es commented 3 years ago

我们是可以通过 js 来描述 dom 结构的,但是用 js 描述非常长,而且结构复杂,因此就出现了 jsx,它是是 JS 语言的一种语法扩展,长的像 html 但他不是 html,jsx 需要通过 babel 转义,react 构造形成 js 结构,再由 react dom 渲染出真实的 dom,并渲染。react 构造过程是调用了 react createElement 函数,它能构造出一个 JS 对象来描述你 HTML 结构的信息,包括标签,属性,还有子元素等。