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> 元素中渲染相应的问候消息。

相关推荐
陈随易40 分钟前
农村程序员-关于小孩教育的思考
前端·后端·程序员
云深时现月41 分钟前
jenkins使用cli发行uni-app到h5
前端·uni-app·jenkins
昨天今天明天好多天1 小时前
【Node.js]
前端·node.js
亿牛云爬虫专家1 小时前
Puppeteer教程:使用CSS选择器点击和爬取动态数据
javascript·css·爬虫·爬虫代理·puppeteer·代理ip
2401_857610031 小时前
深入探索React合成事件(SyntheticEvent):跨浏览器的事件处理利器
前端·javascript·react.js
雾散声声慢1 小时前
前端开发中怎么把链接转为二维码并展示?
前端
熊的猫1 小时前
DOM 规范 — MutationObserver 接口
前端·javascript·chrome·webpack·前端框架·node.js·ecmascript
天农学子1 小时前
Easyui ComboBox 数据加载完成之后过滤数据
前端·javascript·easyui
mez_Blog1 小时前
Vue之插槽(slot)
前端·javascript·vue.js·前端框架·插槽
爱睡D小猪1 小时前
vue文本高亮处理
前端·javascript·vue.js