React是如何渲染元素和组件的

元素的概念

元素是构成 React 应用的最小单位。元素描述了你在屏幕上想看到的内容。React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致。

将一个元素渲染为 DOM

假设我们的 HTML 文件有一个根元素 <div>该节点内的所有内容都将由 React DOM 管理

js 复制代码
<div id="root"></div>

注意: React 构建的应用通常只有单一的根 DOM 节点,如果你想要将 React 集成进一个已有搭建好的应用,那么你可以在应用中包含任意多的独立根 DOM 节点。

将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.render():

js 复制代码
// 已有的应用
<div> 
<h1>Existing App</h1> 
<div id="root1"></div> 
<div id="root2"></div>
</div>
js 复制代码
import ReactDOM from 'react-dom';
// React 组件
const element1 = <h1>Hello, world</h1>;
const element2 = <h1>Hello, world</h1>;
ReactDOM.render(element1, document.getElementById('root1'));
ReactDOM.render(element2, document.getElementById('root2'));

更新已渲染的元素

React 元素是不可变对象。一旦创建,React 元素的子元素和属性就不能直接更改

时钟组件示例:

js 复制代码
    class Clock extends React.Component {
      constructor(props) {
        super(props);
        this.state = {date: new Date()};
      }

      componentDidMount() {
        this.timerID = setInterval(
        //组件挂载到 DOM 后,每一秒调用一次tick()方法
          () => this.tick(),
          1000
        );
      }

      componentWillUnmount() {
        clearInterval(this.timerID);
      }

      tick() {
        this.setState({
       //使用 `setState` 方法更新组件的状态,将 `date` 属性更新为当前时间的 `Date` 对象 
          date: new Date()
        });
      }

      render() {
        return (
          <div>
            <h1>Hello, world!</h1>
            <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
          </div>
        );
      }
    }

    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(<Clock />);

代码分析:

  1. 首先,我们定义了一个名为 Clock 的类,它继承了 React.Component
  2. 在构造函数中,我们初始化了组件的状态(state),其中 date 属性被设置为当前时间的 Date 对象。
  3. 在组件挂载到 DOM 后,componentDidMount 生命周期方法会被调用。在这个方法中,我们创建了一个定时器,并将定时器的 ID 存储在组件的实例变量 timerID 中。定时器每秒触发一次 tick 方法。
  4. tick 方法被调用时,它会使用 setState 方法更新组件的状态,将 date 属性更新为当前时间的 Date 对象。通过调用 setState,React 会检测到状态的变化,并触发重新渲染。
  5. render 方法定义了组件的渲染逻辑。它返回一个包含两个 <h1><h2> 元素的 <div>。其中 <h1> 显示 "Hello, world!",而 <h2> 则显示当前时间,通过访问组件的状态中的 date 属性来获取时间,并使用 toLocaleTimeString 方法将其格式化为本地时间字符串。
  6. 最后,我们使用 ReactDOM.createRoot 创建一个根节点,并将 <Clock /> 组件传递给 root.render 方法,以将组件渲染到指定的根节点上。

这里的生命周期 componentWillUnmount()和 componentDidMount()以及State后面会讲到

注意: 在实践中,大多数 React 应用只会调用一次 ReactDOM.render()。

函数组件与 class 组件

React定义组件的方式主要有两种,函数组件(目前主流)和class组件

函数式组件示例:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

接收唯一带有数据的 "props"(代表属性)对象与并返回一个 React 元素。这类组件被称为"函数组件"

class组件示例

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

使用自定义组件方式:

const element = <Welcome name="zayyo" />;

当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 "props"。在上面的示例中name的值"zayyo"就是组件中的的props.name获取到的值。

过程:

  • 我们调用 root.render() 函数,并传入 <Welcome name="zayyo" /> 作为参数。
  • React 调用 Welcome 组件,并将 {name: 'zayyo'} 作为 props 值传入。
  • Welcome 组件将 <h1>Hello, zayyo</h1> 元素作为返回值。
  • React DOM 将 DOM 高效地更新为 <h1>Hello, zayyo</h1>

注意: 组件名称必须以大写字母开头 。因为React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome

组合组件

我们可以使用多个自定义组件来组成我们的页面。

在下面的代码示例中,将会渲染三个 Welcome 组件,分别显示 "Hello, z"、"Hello, A" 和 "Hello, Y":

js 复制代码
    function Welcome(props) {
      return <h1>Hello, {props.name}</h1>;
    }

    function App() {
      return (
        <div>
          <Welcome name="z" />      
          <Welcome name="A" />     
          <Welcome name="Y" />    
         </div>
      );
    }
    ReactDOM.render(<App />, document.getElementById('root'));

在上面,我们使用 <Welcome name="z" /><Welcome name="A" /><Welcome name="Y" /> 分别创建了三个 Welcome 组件的实例,并将它们放置在 <div> 中。

每个 Welcome 组件都会接收不同的 name 属性值,通过 props.name 来访问该属性值,并在组件内部的 <h1> 元素中渲染相应的问候消息。

相关推荐
Tandy12356_3 分钟前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20026 分钟前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包
你会发光哎u10 分钟前
Webpack模式-Resolve-本地服务器
服务器·前端·webpack
王小二(海阔天空)10 分钟前
个人文章合集 - 前端相关
前端·css·vue·jquery
老华带你飞19 分钟前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计
gopher951136 分钟前
HTML详解
前端·html
Tiny201737 分钟前
前端模块化CommonJs、ESM、AMD总结
前端
吕永强39 分钟前
CSS相关属性和显示模式
前端·css·css3
结衣结衣.44 分钟前
python中的函数介绍
java·c语言·开发语言·前端·笔记·python·学习
全栈技术负责人1 小时前
前端提升方向
前端