...

【跟着ChatGPT学React】核心库

React 核心库

写在前面的,这里的ChatGPT是根据2025年1月15日节点书写的。这里随时更新。

首先你要知道为什么出现 React 这种库,难道原来的库不行吗?一直以来操作 jquery 的不香吗?

组件化模式

命令式编码 → 让 dom 干嘛你干嘛 其实比如说获取 dom,操作 dom 这种。就是说你通过数据来操纵视图。比如 user 是 true,你就是显示已经登录页面的个人资料。然后 JavaScript 自己就会重新通过数据渲染页面。

声明式代码 → 我告诉你页面应该是什么样子的,然后 react 帮你全干了。 是结果导向的。

因为JS 和 JQ 那种原生操作 DOM 会浪费大量资源,因为每一次都是更新都是重新渲染进行 repaint,然后 refloat,recalculte the layout。change dom is really expensive operation

关于这里,有一个知乎声明式编程和命令式编程有什么区别?

1 三大核心库

先看 ChatGPT 回答

引入了三个核心库:react.development.jsreact-dom.development.jsbabel.min.js。它们分别有以下作用:

  1. react.development.js (React 核心库)
  2. React 对象:这是 React 框架的核心库。它提供了创建 React 组件和虚拟 DOM 元素的能力。
  3. JSX:这个库也包含 JSX 的语法,JSX 是一个看起来像 XML 的 JavaScript 语法扩展。它可以更简洁地描述 UI 组件。
  4. 组件生命周期:React 组件的生命周期方法和 hooks 也定义在这里。
  5. react-dom.development.js (ReactDOM 库)
  6. ReactDOM 对象:此库提供与浏览器 DOM 交互的能力。React 本身只关心组件和虚拟 DOM,而 ReactDOM 关心如何将这些虚拟 DOM 渲染到实际的浏览器 DOM 中。
  7. render 方法:如你在示例中所示,ReactDOM.render() 方法就是用来将 React 元素(或组件)渲染到 DOM 容器中的。
  8. babel.min.js (Babel 库)
  9. JSX 到 JavaScript 的转化:浏览器原生是不支持 JSX 语法的。Babel 提供了一个转换器,可以将 JSX 转换为浏览器可以执行的普通 JavaScript。
  10. 新的 JavaScript 特性:Babel 不仅仅转换 JSX,它还可以将 ES6+的 JavaScript 代码转换为大多数浏览器都能理解的 ES5 代码。这使得开发者可以使用最新的 JavaScript 特性而不必担心兼容性问题。

  11. React:负责应用的逻辑、状态管理、组件的定义及生命周期等。当组件的状态改变或接收到新的 props 时,React 会在内存中构建一个新的虚拟 DOM 树。React 也提供了组件间的交互方式、生命周期方法和 Hooks 等。

  12. ReactDOM:作为一个桥梁,它的主要职责是将虚拟 DOM 渲染到真实的 DOM。为此,它会:
  13. 比较新旧两个虚拟 DOM 树,计算它们之间的差异。
  14. 基于这些差异,更新真实的 DOM,使其与最新的虚拟 DOM 树同步。
  15. 提供了一些特定于浏览器环境的工具和方法,如ReactDOM.render()ReactDOM.createPortal()

这种分工使得 React 框架更加模块化和灵活。因为核心 React 库与渲染目标(如浏览器 DOM、原生移动应用等)是解耦的,所以可以容易地将 React 与不同的渲染库(如ReactDOMReact NativeReact VR等)结合使用。

1-1 react.js 核心库

这个没什么好说的,必须要有,React 核心库。引入核心库,要先引入 。数据 → VDOM。

1-2 react-dom.js

提供操作 DOM 的 react 扩展库。上面引入了这个才可以,用于 react 操作 DOM。VDOM → DOM。

reactDOM.render(虚拟DOM,真实DOM)

// ReactDOM.render(虚拟DOM,真实DOM)  
ReactDOM.render(VDOM, document.getElementById('test'));  

这里提到了虚拟 DOM,那么虚拟 DOM 是怎么来的。

① 生成虚拟 DOM React.createElement()

这个是核心库的用法。这是最基础的方法,通过`()生成的是一个虚拟 DOM 对象。

const button = React.createElement(  
  'button',  
  {  
    type: 'button',  
    className: 'hello',  
    onClick: () => {  
      alert('ok');  
    },  
  },  
  'click me!!'  
);  
// 👇🏻 实际在网页生成的就是一个div元素  
// 因为无需用jsx的话,不需要babel了  
<script type="text/javascript" src="../js/babel.min.js"></script>  
<script type="text/babel" >  
React.createElement(标签名,属性,内容);  

const vDom1 = React.createElement('h2',React.createElement(在这里无限嵌套),内容)  

但是当标签多了之后会有写起来就是一个无线嵌套,所以实际上很少有人这么写。

const vDom1 = React.createElement(  
  'h2',  
  React.createElement(在这里无限嵌套),  
  内容  
);  

⚠️ 虚拟 DOM 肯定不只是一个啊,然后就会发生。无线嵌套。所以方法二就出来了。

② 生成虚拟 DOM JSX

const VDOM = '<h1>Hello,React</h1>'; /* ❌ 这种只是字符串 */  
const VDOM = (  
  <h1>Hello,React</h1>  
); /* ✅ 此处一定不要写引号,因为不是字符串 这就是JSX */  

这个单独下面写,先说下 JSX 如果想转换成 JS 的那种虚拟 DOM 需要三大核心库的最后一个也就是 babel

<script type="text/babel">  
  {' '}  
  /* 此处一定要写babel */ // 1.创建虚拟DOM 用()这样表示一个整体 这样更像一个整体  
  const VDOM = ( /* 此处一定不要写引号,因为不是字符串 */  
  <h1 id="title">  
    <span>Hello,React</span>  
  </h1>  
  ) // 2.渲染虚拟DOM到页面 ReactDOM.render(VDOM,document.getElementById('test'))  
</script>  

1-3 babel.min.js

bable 在 react 主要作用其实就是 2 个。

作用 1 ES6 → ES5

作用 2 JSX → JS

<!DOCTYPE html>  
<html lang="en">  
  <head>  
    <meta charset="UTF-8" />  
    <title>hello_react</title>  
  </head>  
  <body>  
    <!-- 准备好一个“容器” -->  
    <div id="test"></div>  

    <!-- 引入react核心库 多了一个React -->  
    <script type="text/javascript" src="../js/react.development.js"></script>  
    <!-- 引入react-dom,用于支持react操作DOM 多了一个ReactDOM对象 -->  
    <script  
      type="text/javascript"  
      src="../js/react-dom.development.js"  
    ></script>  
    <!-- 引入babel,用于将jsx转为js -->  
    <script type="text/javascript" src="../js/babel.min.js"></script>  

    <script type="text/babel">  
      /* 此处一定要写babel 而不是写jsx */  
      //1.创建虚拟DOM  
      const VDOM = (  
        <h1>Hello,React</h1>  
      ); /* 此处一定不要写引号,因为不是字符串 这就是JSX */  
      //2.渲染虚拟DOM到页面(虚拟DOM,容器)  
      ReactDOM.render(VDOM, document.getElementById('test'));  
    </script>  
  </body>  
</html>  

👆 写的都是最基础的引入方式,是为了学习语法,真正开发的时候是不推荐这样直接引入的,因为浏览器在遇到<script type="text/babel" >的时候才会进行翻译。

ReactDOM.render(VDOM, document.getElementById('test'));  
ReactDOM.render(VDOM2, document.getElementById('test'));  
// ⚠️ 以上写了俩个虚拟dom,但其实后面的会覆盖掉前面的。  
// 重复调用render(),会进行diff比较,确保只修改发生变化的元素。  
// React虚拟dom一旦创建就无法修改,只能通过创建新的。只会对第二个DOM进行替换掉,重新渲染。  
//  为什么不是在基础上修改,而是整体替换?这样效率能高吗?  
//  React内部会对比有一个diff算法,所以效率会很低。  

2 虚拟 DOM PK 真实 DOM

为什么要用虚拟 DOM? 因为操作真实的 DOM 是特别没有效率的事情。

  • 减少原生 DOM 的 API
  • 解决兼容问题
  • 提升性能(不发生变化的情况下,都不会被 diff 渲染。

其实这也是 react 的特色,就是先通过生成虚拟 DOM,然后在生成真实 DOM,最后渲染。

为什么不用 XML,因为是这个 XML 的标签数据结构性的内容比数据还多。特别繁琐,没有效率。

虚拟 DOM

// 创建虚拟DOM  
const VDOM = (  
  /* 此处一定不要写引号,因为不是字符串 */  
  <h1 id="title">  
    <span>Hello,React</span>  
  </h1>  
);  
// 渲染虚拟DOM到页面  
ReactDOM.render(VDOM, document.getElementById('test'));  

真实 DOM

// 创建真实DOM  
const TDOM = document.getElementById('demo');  
console.log('虚拟DOM', VDOM);  
console.log('真实DOM', TDOM);  
debugger; // 在这里可以看出真实DOM会有很多不需要的属性很重  
// console.log(typeof VDOM);  
// console.log(VDOM instanceof Object);  

关于虚拟 DOM 的本质

  1. 本质是 Object 类型的对象(是一般对象{} 因为不是数组对象,也不是函数对象)
  2. 虚拟 DOM 比较“轻”,真实 DOM 比较“重”,因为虚拟 DOM 是 React 内部在用,无需真实 DOM 上那么多的属性。
  3. 虚拟 DOM 最终会被 React 转化为真实 DOM,呈现在页面上。

关于 React18

在 18 以前,渲染是这样的。

ReactDOM.render(虚拟的DOM, JS原生获取真实的DOM);  
// 通过render这个函数,把虚拟DOM渲染到真实DOM上  
ReactDOM.render(<App />, document.getElementById('root'));  

但是 18 的时候,采取了新的方式

// 自己先创建 root节点,通过root节点来渲染  
// 就是要插入的位置,从此开始所有的操作都要交给react了  
const root = ReactDOM.createRoot(document.getElementById('root'));  
// react元素渲染到根元素,真实的root下的内容都会被删除  
// 全部交给了虚拟DOM里  
// 重复调用render(),会进行diff比较,确保只修改发生变化的元素。  
root.render(虚拟DOM);  

其实这个意思大概率就是每一次渲染不用总是 document.getElementById('root');

共有评论(0)

登陆即可评论哦