React 运作原理 & JSX

React 运作原理

在原生的 JavaScript 里,我们会操作 DOM 来修改网页程序码,但这麽做会很容易不小心改到不需要变动的地方,React 解决了这件事,让 React 程序码在更新 DOM 之前,先用 JavaScript 制造出虚拟的 DOM - Virtual DOM,利用这个 Virtual DOM 模拟所有更新後应该要长的样子,设计一个特殊的 Diff 演算法去比较当前的 DOM 和 模拟出的虚拟 DOM 的差别,最後 React 只会去修改有不一样的地方,避免资源的浪费。

首先来看看下面这三行程序码:
第一行为导入 React
第二行为导入 ReactDOM
第三行为开发 React 程序的进入点,让所有 React 程序码透过 ReactDOM 提供的 render 函式绑定到 HTML 里,render 的第一个参数是要渲染到画面上的元素,第二个参数决定元素要放到哪个 HTML 元素内。

// 获得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 渲染到画面上
ReactDom.render(<div>Hello, World></div>, document.querySelector("#root"));

第三行将 <div>Hello, World></div> 绑定到 <div id="root"></div>,而这个 html 档案会在 public 资料夹里面的 index.html,打开会发现 body 里面有个 id 为 root 的 div 元素,这就是我们绑定 React 程序的地方,所有专案的元素都会被 React 包进 index.html 的 <div id="root"></div> 里面。

下面只是为了理解 React 背後的原理,所以使用 React.createElement,但平常不会使用这些做法,而会使用 JSX

  • 制作单一元素
    React.createElement("HTML tag", css设定, "HTML tag 的内容")
    index.js
// 获得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 制作 h1
function App() {
  return React.createElement("h1", null, "This is React App.");
}
// ReactDOM.render(渲染的内容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));

由此可知 React 的原理为,用 function 制造出 Element,再选定 HTML 文件的某个地方让创造出来的 Element 显示到那里。

  • 制作多个元素

因为一个 function 不能 return 好几个值,所以要制作多个 html 标签的话,在 React.createElement() 里面的第 3 个参数要是一个 Array。

// 获得 React & ReactDom module
import React from "react";
import ReactDOM from "react-dom";
// 制作 div,里面放 h1,p,button
function App() {
  return React.createElement("div", null, [
    React.createElement("h1", { style: { color: "red" } }, "My Profile."),
    React.createElement("p", null, "My Name is Helen."),
    React.createElement("button", null, "Check my profile."),
  ]);
}
// ReactDOM.render(渲染的内容,要渲染的位置)
ReactDom.render(React.createElement(App), document.querySelector("#root"));


上面的例子使用了复杂的 JavaScript 建构出 React component,为了使开发更有效率,我们会需要 JSX。

JSX

假如我们写这样的 code:const h1 = <h1>Hello world</h1>,这样运作时根本不会起作用,因为在 JavaScript 里不能包含 HTML,所以当这样写的时候浏览器看不懂,而 JSX 就是让我们在写 React 时,可以把 JavaScript 写得很像 HTML,让我们在 JavaScript 里可以使用标签式的语法来写 React,且内建 Babel 功能,会自动将 JSX 编译成浏览器能理解的 JavaScript(JSX 会被编译成前面提到的 React.createElement 的作法)。

  • 要注意 2 件事:
  1. 所有的 function 只能 return 一个值,所以当里面放很多个元素时,就要用一个封闭的标签包起来,例如 div。
  2. function 的名称开头一定要是大写,不可为小写,大写才会被当成 component,写小写的话会被浏览器以为是 HTML tag。

将上面 React.createElement 的程序码改为 JSX :

// 获得 React & ReactDom module
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

// JSX
function App() {
  return (
    <div>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </div>
  );
}
// ReactDOM.render(渲染的内容,要渲染的位置)
ReactDom.render(<App />, document.querySelector("#root"));

  • React Fragment
    上面的内容有提到,如果想要在 React 同时渲染多个元素时,我们必须将元素包在一个封闭的标签里面,但这种作法会产生许多没有意义的标签,React Fragment 可以为我们省去额外多余的容器,使 DOM 的结构更乾净。
    将上面的程序码由 div 改成 React Fragment:
import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <React.Fragment>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </React.Fragment>
  );
}

ReactDom.render(<App />, document.querySelector("#root"));

也可以使用 React.Fragment 的简写语法:

import { div } from "prelude-ls";
import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <>
      <h1 style={{ color: "red" }}>My Profile.</h1>
      <p>My Name is Helen.</p>
      <button>Check my profile.</button>
    </>
  );
}

ReactDom.render(<App />, document.querySelector("#root"));

使用 React.Fragment 後,如果去检视 DOM,会发现并没有渲染成任何标签

<div id="root">
  略
<div/>
  • 在 JSX 里加入 CSS 的方式

在 tag 里加入 style={{ }},第一个括号表示传参数,第二个表示参数里的 CSS 设定
例如:<h1 style={{ color: "red" }}>My Profile.</h1>

  • 在 JSX 里,写入 JavaScript 需要使用大括号 { } 包覆

例如:<h1>{ title.toUpperCase() }</h1>
因为大括号里代表写入的 JavaScript,h1 的内容会变成 TITLE

  • className, htmlFor

因为在 JavaScript 中已经有 class 和 for,当我们在写 JSX 时,会以 className 来表示 HTML 的 class 属性,而以 htmlFor 表示 for。
例如:<h1 className="title">Hello World</h1>

参考资料:
一本在诚品看到的书,忘记书名是什麽了 XD


<<:  [神经机器翻译理论与实作] 将Encoder、Decoder和Attention统统包起来

>>:  【後转前要多久】# Day18 BootStrap - 快速看文件

[DAY7]制作容器(六)

改成ubuntu的image docker run -it --name cont3-cakephp...

Day8:终於要进去新手村了-Javascript-资料型态

上一篇文章讲到的是变数以及将资料放进变数里面,那这一篇讲到的会是关於资料的类型。 这篇主要讲的是类型...

初学者跪着学JavaScript Day17: 物件:new Set()

一日客语:中文:不好意思 客语:paiˇse! ㄆㄞˇ 厶ㄟ 1.set 是一个集合 2.集合没有索...

【没钱买ps,PyQt自己写】Day 9 - 以 QLineEdit, QTextEdit, QPlainTextEdit 作为文字的输入

看完这篇文章你会得到的成果图 前言 我们接下来的讨论,会基於读者已经先读过我 day5 文章 的架构...

用React刻自己的投资Dashboard Day1 - 前言

tags: 2021铁人赛 React 系列文想法来源 因为笔者本身在金融业工作,日常生活中时常关注...