(一)手写 React 源码之准备阶段

学习点

相关的基本概念如:虚拟 DOM、JSX 等

代码仓库:github.com/kjhuanhao/j...

React 是什么

需求:在页面上显示一个按钮,按钮显示的文字内容为:Hello, Count:0,每点击一次该按钮,count 的数字加1

JS实现

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #content {
      font-size: 22px;
      border: 1px solid grey;
      cursor: pointer;
      padding: 6px 10px;
      display: inline-block;
      border-radius: 10px;
    }
  </style>
</head>
<body>
  <div id="root">
    <div id="content" onclick="changeText()">Click Me, Count: 0</div>
  </div>
  <script lang="javascript">
    let count = 0;
    function changeText() {
      count++;
      document.getElementById("content").innerHTML = `Click Me, Count: ${count}`;
    }
  </script>
</body>
</html>

React实现

javascript 复制代码
import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

初始准备

初始化一个 React 项目

初始化之后删除掉无用的代码和文件,以便我们可以更好去学习

  • index.js
javascript 复制代码
import ReactDOM from 'react-dom/client';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<div>Simple React</div>);
  • index.html
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Simple React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

虚拟 DOM

DOM 是 html 的编程接口,通过 DOM 的方式可以操作文档的结构、样式和内容

  1. DOM 是针对 html、xml 编程接口和编程语言无关
  2. DOM 实现相当于一个独立的程序,可以用 js、java、python 实现
  3. 而通过DOM 实现可以获取一个 DOM 对象,从而操作 DOM 对象
javascript 复制代码
let element = document.getElementById('root')
let obj = {}
for (let key in element){ obj[key] = element[key]}
console.log(obj) 

可以通过代码去修改 DOM 对象,但是开销会非常大,所以引入了虚拟 DOM,虚拟 DOM 是用于描述 DOM对象的对象,在 js 中绝大部分的 DOM 对象的都是非必需的

在 react 中直接打印一个react 对象

javascript 复制代码
console.log(<div>Simple React</div>)

总之,对比来看

  1. 没有虚拟 DOM 的情况下,直接操作一个 DOM 对象,其发生的变化需要遍历整棵 DOM 树
  2. 有虚拟 DOM 的情况下,直接操作一个 DOM 对象就是操作其虚拟 DOM,根据前后两个虚拟 DOM 之间的变化,可以计算出页面需要变化的地方

JSX 相关概念

JSX 是 JavaScript 的语法扩展,他既不是 js 也不是 html,通常我们使用 babel 来进行 jsx 的转换

JSX 相关概念

JSX 是 JavaScript 的语法扩展

  • 新的转换形式
javascript 复制代码
import ReactDOM from 'react-dom/client';

const root = ReactDOM.createRoot(document.getElementById('root'));
let element = <div>Hello</div>
root.render(element);

编译后会变成这样的 js 代码,为什么刚刚在 babel 中会有所不同

javascript 复制代码
let element = /*#__PURE__*/(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxDEV)("div", {
  children: "Hello"
}, void 0, false, {
  fileName: _jsxFileName,
  lineNumber: 4,
  columnNumber: 15
}, undefined);

babel编译后的,实际上是因为开发环境和生产环境的不同导致的

javascript 复制代码
import { jsx as _jsx } from "react/jsx-runtime";
const element = /*#__PURE__*/_jsx("div", {
  children: "123"
});

不管是哪种方式,它们返回的都是一个虚拟 DOM 对象

  • 旧的转换形式,需要导入 React
javascript 复制代码
import React from 'react';
let element = <div>Hello</div>
React.createElement("div", null, "Hello")

React 和 ReactDOM 的职责划分

  • react:组件相关核心 API 的暴露
  • react-dom:和 react 配套,将写好的组件进行渲染
相关推荐
前端架构师-老李8 小时前
React 中 useCallback 的基本使用和原理解析
前端·react.js·前端框架
阿蓝灬10 小时前
React中的stopPropagation和preventDefault
前端·javascript·react.js
崽崽的谷雨10 小时前
react使用ag-grid及常用api笔记
笔记·react.js·ag-grid
前端小咸鱼一条10 小时前
17.React获取DOM的方式
前端·javascript·react.js
AKclown12 小时前
基于Monaco的diffEditor实现内容对比
前端·vue.js·react.js
chenbin___12 小时前
react native中 createAsyncThunk 的详细说明,及用法示例(转自通义千问)
javascript·react native·react.js
向日葵同志4433013 小时前
使用@univerjs纯前端渲染excel, 显示图片、链接、样式
前端·react.js·excel
梦65014 小时前
什么是react?
前端·react.js·前端框架
wyzqhhhh14 小时前
同时打开两个浏览器页面,关闭 A 页面的时候,要求 B 页面同时关闭,怎么实现?
前端·javascript·react.js
西部森林牧歌14 小时前
Arbess零基础学习 - 使用Arbess+GitLab实现 React.js 项目自动化构建/主机部署
react.js·ci/cd·arbess·tiklab devops