浏览器渲染原理-构建阶段

浏览器渲染原理-解析阶段

解析阶段获取到DOM和CSSOM后,进入渲染树构建阶段

任务

将DOM和CSSOM相结合,给每一个可见DOM节点创建渲染对象,将这些渲染对象参照DOM树结构结合起来,形成"清洗后赋予样式的DOM树"(渲染树)

流程

渲染阶段主要分为5个步骤

  1. 遍历DOM树
  2. 去除不可见节点
  3. 生成渲染对象
  4. 应用CSS
  5. 生成渲染树

其中2~5是一个重复的过程,针对于每一个DOM节点

步骤详情描述

  • 遍历DOM树

一个递归的过程(深度优先搜索DFS),依次从DOM根节点读取每一个节点

  • 去除不可见节点

去除不可见节点分为两种情况 情况一:初始遍历DOM时 初始遍历DOM时,会去除一些常见不可见标签(head、link、style、script等)以及在解析阶段已经能够判断出不可见的节点(<div style="display: none;"></div>)。 情况二:应用完成CSS后 节点应用完成CSS后,挂载到渲染树之前,会判断节点是否可见,如果不可见,节点将不会被挂载。

  • 生成渲染对象

渲染对象在初次遍历DOM时创建,记录DOM的嵌套信息并注入一些DOM操作API(如:appendChild)。

  • 应用CSS

遍历CSSOM规则列表,筛选命中的样式,每一个属性根据CSS选择器优先级计算出最终样式。最终样式注入到渲染对象的styles属性。

  • 构建渲染树

将可见的渲染对象参考DOM结构,挂载到对应位置。 渲染树构建是一个逐步的过程,每生成一个渲染对象就挂载一个节点,最终构成一棵树结构。

生成规则样例

构建伪代码

js 复制代码
function buildRenderTree(domNode) {
    // 跳过不可见节点
    if (isHidden(domNode)) return null;

    // 创建渲染对象
    const renderObject = createRenderObject(domNode);

    // 递归遍历子节点并构建子渲染对象
    let child = domNode.firstChild;
    while (child) {
        const childRenderObject = buildRenderTree(child);
        if (childRenderObject) {
            renderObject.appendChild(childRenderObject);
        }
        child = child.nextSibling;
    }

    return renderObject;
}

function isHidden(domNode) {
    if (domNode.nodeType === Node.ELEMENT_NODE) {
        const style = window.getComputedStyle(domNode);
        return style.display === 'none';
    }
    return false;
}

function createRenderObject(domNode) {
    const renderObject = {
        // 渲染对象结构
        styles: window.getComputedStyle(domNode),
        children: [],
        appendChild: function(child) {
            this.children.push(child);
        }
    };
    return renderObject;
}

// 示例调用,从根节点开始构建渲染树
const renderTree = buildRenderTree(document.documentElement);
console.log(renderTree);

渲染树结构

js 复制代码
// html
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial; }
        .container { color: blue; }
        p { font-size: 16px; }
        .hidden { display: none; }
    </style>
</head>
<body>
    <div class="container">
        <p>Hello, World!</p>
        <p class="hidden">This is hidden</p>
    </div>
</body>
</html>

Document
└── html
    ├── head
    └── body
        └── div.container
            ├── p
            │   └── "Hello, World!"
            └── p.hidden
                └── "This is hidden"

CSSOM
└── Stylesheet
    ├── Rule: body { font-family: Arial; }
    ├── Rule: .container { color: blue; }
    ├── Rule: p { font-size: 16px; }
    └── Rule: .hidden { display: none; }

RenderRoot
└── RenderBody (type: 'block', styles: { font-family: 'Arial' })
    └── RenderBlock (type: 'block', styles: { color: 'blue' })
        └── RenderParagraph (type: 'block', styles: { font-size: '16px' })
            └── RenderText (type: 'inline', styles: {}, text: 'Hello, World!')

构建阶段得到渲染树后,进入布局阶段

相关推荐
真的很上进1 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203987 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_23428 分钟前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1231 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~2 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww2 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254882 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui