当前位置: 首页 > article >正文

【React】函数组件底层渲染机制

目录

  • 函数组件
    • 创建
    • 调用&命名
    • 组件传参
    • 渲染机制
    • 对属性props的处理
  • 关于对象的规则设置
    • 冻结
    • 密封
    • 扩展

函数组件

创建

创建一个函数,让函数返回JSX视图「或者JSX元素、virtualDOM虚拟DOM对象」,就是创建了一个“函数组件”。

const DemoOne = function DemoOne(props) {
    return <div className="demo-box">
        <h2 className="title">Hello,world</h2>
    </div>;
}; 

调用&命名

基于ES6Module规范,导入创建的组件「可以忽略.jsx后缀名」,然后像写标签一样调用这个组件即可。组件的名字,一般都采用PascalCase「大驼峰命名法」这种方式命名。

<Component/> 单闭合调用
<Component> ... </Component> 双闭合调用
import DemoOne from './views/DemoOne';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <DemoOne />
)

组件传参

调用组件的时候,我们可以给调用的组件设置(传递)各种各样的属性

<DemoOne title="我是标题" x={10} data={[100, 200]} className="box" style={{ fontSize: '20px' }} />
  • 如果设置的属性值不是字符串格式,需要基于{}进行嵌套
  • 调用组件的时候,我们可以把一些数据/信息基于属性props的方式,传递给组件

打印子组件接收到的参数:

const DemoOne = function DemoOne(props) {
    console.log(props,'props')
    const {title,x,data,style,className} = props;
    return <div className="demo-box">
    <h2 className="title">Hello,world</h2>
</div>;
};

在这里插入图片描述

渲染机制

1、基于babel-preset-react-app把调用的组件转换成createElement格式

<DemoOne title="我是标题" x={10} data={[100, 200]} className="box" style={{ fontSize: '20px' }} />

上面JSX语法经过babel-preset-react-app编译为如下:

import { jsx as _jsx } from "react/jsx-runtime";
createElement(DemoOne, {
  title: "\u6211\u662F\u6807\u9898",
  x: 10,
  data: [100, 200],
  className: "box",
  style: {
    fontSize: '20px'
  }
});

2、执行createElement方法,创建出一个virtualDOM对象

     {
            $$typeof: Symbol(react.element),
            key: null,
            props: {title: '我是标题', x: 10, data: 数组, className: 'box', style: {fontSize: '20px'}}, //如果有子节点「双闭合调用」,则也包含children!!
            ref: null,
            type: DemoOne //函数类型
        }

3、基于root.render把virtualDOM变为真实DOM

此时 type 值不再是一个字符串,而是一个函数,此时:

  • 会把函数执行 -> DemoOne()
  • 把virtualDOM中的props,作为实参传递给函数 -> DemoOne(props)
  • 接收函数执行的返回结果「也就是当前组件的virtualDOM对象」
  • 最后基于render把组件返回的虚拟DOM变为真实DOM,插入到#root容器

对属性props的处理

调用组件,传进来的props是可读的,不可修改,可以通过Object.isFrozen(props) 进行判断:

const DemoOne = function DemoOne(props) {
    console.log(Object.isFrozen(props)) //结果为true,说明props传进来被冻结了;
    const {title,x,data,style,className} = props;
    return <div className="demo-box">
    <h2 className="title">Hello,world</h2>
</div>;

如果修改props中的值就会报错,如下:

const DemoOne = function DemoOne(props) {
    props.title = "你好";
    return <div className="demo-box">
    <h2 className="title">{title}</h2>
</div>;
};

在这里插入图片描述
虽然对于传递进来的属性,我们不能直接修改,但是可以做一些规则校验

  • 设置默认值
DemoOne.defaultProps = {
    x: 0
};
  • 设置参数类型,需要用到prop-types插件, https://github.com/facebook/prop-types,传递进来的属性,首先会经历规则的校验,不管校验成功还是失败,最后都会把属性给形参props,只不过如果不符合设定的规则,控制台会抛出警告错误(不影响属性值的获取)
import PropTypes from 'prop-types';
函数组件.propTypes = {
        // 类型是字符串、必传
        title: PropTypes.string.isRequired,
        // 类型是数字
        x: PropTypes.number,
        // 多种校验规则中的一个
        y: PropTypes.oneOfType([
            PropTypes.number,
            PropTypes.bool,
        ])
      };

如果想把传递的属性值进行修改,可以:

  • 把props中的某个属性赋值给其他内容「例如:变量、状态…」
  • 我们不直接操作props.xxx=xxx,但是我们可以修改变量/状态值
const DemoOne = function DemoOne(props) {
    console.log(props, 'props')
    let { title, x, data, style, className } = props;
    return <div className="demo-box">
        <h2 className="title">{title}</h2>
    </div>;
};

关于对象的规则设置

冻结

  • 冻结对象:Object.freeze(obj)
  • 检测是否被冻结:Object.isFrozen(obj) =>true/false
  • 被冻结的对象:不能修改成员值、不能新增成员、不能删除现有成员、不能给成员做劫持「Object.defineProperty

密封

  • 密封对象:Object.seal(obj)
  • 检测是否被密封:Object.isSealed(obj)
  • 被密封的对象:可以修改成员的值,但也不能删、不能新增、不能劫持!!

扩展

  • 把对象设置为不可扩展:Object.preventExtensions(obj)
  • 检测是否可扩展:Object.isExtensible(obj)
  • 被设置不可扩展的对象:除了不能新增成员、其余的操作都可以处理!!
  • 被冻结的对象,即是不可扩展的,也是密封的!!同理,被密封的对象,也是不可扩展的!!

http://www.kler.cn/a/508016.html

相关文章:

  • ZooKeeper 核心概念与机制深度解析
  • redis实现限流
  • 文件上传 分片上传
  • SurfaceFlinger代码笔记
  • http转化为https生成自签名证书
  • 传统摄像头普通形态的系统连接方式
  • 【2024年华为OD机试】 (B卷,200分)- 二叉树中序遍历(Java JS PythonC/C++)
  • GIFT ICA 下载记录
  • Flink的优化技巧
  • 力扣-数据结构-21【算法学习day.92】
  • 如何选择适合特定项目需求的人工智能学习框架?
  • python-44-嵌入式数据库SQLite和DuckDB
  • SQL-杂记1
  • C++11特性简述
  • 恒生科技OK吗?低频量化日报(明日涨停预测,指数数据,可转债上市价格预测)...
  • 2025.1.15——八、ua注入
  • SpringBoot入门实现简单增删改查
  • 基于springboot的快速集成多数据源的启动器
  • 数据结构-栈队列OJ题
  • C语言的循环实现
  • Spring6.0新特性-HTTP接口:使用@HttpExchange实现更优雅的Http客户端
  • 6G移动通信技术:相较于5G的改进点与技术实现
  • 【Python】函数 超全总结及练习案例
  • PHP:写接口与接口的调用(完整版,封装公共方法)
  • 【Docker系列】SpringBoot 项目如何动态指定配置文件
  • 国家统计局湖北调查总队副总队长张小青一行调研珈和科技农业遥感调查智能化算法