react 组件设计模式

首先我们想一个问题,那就是 为什么要学习设计模式? 原因我总结有以下几个方面。 1. 功能复杂,逻辑复用问题。 首先 React 灵活多变性,就决定了 React 项目可以应用多种设计模式。但是这些设计模式的产生也确实办了实事: 场景一: 在一个项目中,全局有一个状态,可以称之为 theme (主题),那么有很多 UI 功能组件需要这个主题,而且这个主题是可以切换的,就像 github 切换暗黑模式一样,那么如何优雅的实现这个功能呢? 这个场景如果我们用 React 的提供者模式,就能轻松搞定了,通过 context 保存全局的主题,然后将 theme 通过 Provider 形式传递下去,需要 theme ,那么消费 context ,就可以了,这样的好处是,只要 theme 改变,消费 context 的组件就会重新更新,达到了切换主题的目的。 场景二: 表单设计场景也需要一定程度上的 React 的设计模式,首先对于表单状态的整体验证需要外层的 Form 绑定事件控制,调度表单的状态下发,验证功能。内层对于每一个表单控件还需要 FormItem 收集数据,让控件变成受控的。 这样的 Form 和 FormItem 方式,就是通过组合模式实现的。 2. 培养设计能力,编程能力 熟练运用 React 的设计模式,可以培养开发者的设计能力,比如 HOC 的设计 ,公共组件的设计 ,自定义 hooks 的设计,一些开源的优秀的库就是通过 React 的灵活性和优秀的设计模式实现的。 例子: 比如在 React 状态管理工具中,无论是 react-redux ,还是 mobx-react,一方面想要把 state 和 dispatch 函数传递给组件,另一方面订阅 state 变化,来促使业务组件更新,那么整个流程中,需要一个或多个 HOC 来搞定。于是 react-redux 提供了 connect,mobx-react 提供了 inject ,observer 等优秀的 hoc。由此可见,学会 React 的设计模式,有助于开发者小到编写公共组件,大到开发开源项目。 ...

December 17, 2024

字符串常见方法

1. 获取字符串长度 JavaScript中的字符串有一个length属性,该属性可以用来获取字符串的长度: const str = 'hello'; str.length // 输出结果:5 2. 获取字符串指定位置的值 charAt()和charCodeAt()方法都可以通过索引来获取指定位置的值: charAt() 方法获取到的是指定位置的字符; charCodeAt()方法获取的是指定位置字符的Unicode值。 (1)charAt() charAt() 方法可以返回指定位置的字符。其语法如下: string.charAt(index) index表示字符在字符串中的索引值: const str = 'hello'; str.charAt(1) // 输出结果:e 我们知道,字符串也可以通过索引值来直接获取对应字符,那它和charAt()有什么区别呢?来看例子: const str = 'hello'; str.charAt(1) // 输出结果:e str[1] // 输出结果:e str.charAt(5) // 输出结果:'' str[5] // 输出结果:undefined 可以看到,当index的取值不在str的长度范围内时,str[index]会返回undefined,而charAt(index)会返回空字符串;除此之外,str[index]不兼容ie6-ie8,charAt(index)可以兼容。 (2)charCodeAt() charCodeAt():该方法会返回指定索引位置字符的 Unicode 值,返回值是 0 - 65535 之间的整数,表示给定索引处的 UTF-16 代码单元,如果指定位置没有字符,将返回 NaN: let str = "abcdefg"; console.log(str.charCodeAt(1)); // "b" --> 98 通过这个方法,可以获取字符串中指定Unicode编码值范围的字符。比如,数字0~9的Unicode编码范围是: 48~57,可以通过这个方法来筛选字符串中的数字,当然如果你更熟悉正则表达式,会更方便。 3. 检索字符串是否包含特定序列 这5个方法都可以用来检索一个字符串中是否包含特定的序列。其中前两个方法得到的指定元素的索引值,并且只会返回第一次匹配到的值的位置。后三个方法返回的是布尔值,表示是否匹配到指定的值。 注意:这5个方法都对大小写敏感! (1)indexOf() indexOf():查找某个字符,有则返回第一次匹配到的位置,否则返回-1,其语法如下: string.indexOf(searchvalue,fromindex) 该方法有两个参数: searchvalue:必需,规定需检索的字符串值; fromindex:可选的整数参数,规定在字符串中开始检索的位置。它的合法取值是 0 到 string.length - 1。如省略该,则从字符串的首字符开始检索。 let str = "abcdefgabc"; console.log(str.indexOf("a")); // 输出结果:0 console.log(str.indexOf("z")); // 输出结果:-1 console.log(str.indexOf("c", 4)) // 输出结果:9 (2)lastIndexOf() lastIndexOf():查找某个字符,有则返回最后一次匹配到的位置,否则返回-1 ...

November 8, 2024

SEO

🌻 前言 SEO 代表搜寻引擎最佳化/搜寻引擎优化(英文全名Search Engine Optimization,简称SEO),是指通过了解搜寻引擎的自然排名的算法逻辑,以提高目标网站在有关搜寻引擎内排名的方式。 网站的 SEO 至关重要,它可以让你的网站获得更好的排名和流量,从而提高网站知名度。对于一些盈利的网站,做好seo,还可以以低成本提高投资回报率。 本文将为你带来非常全面的SEO方案🔥🔥🔥,当然了,网站SEO是长线工作,在做好一些基础的配置之后,更重要的是后期的维护,比如定期更新网站动态文章,不断寻找优质外链资源等🤌。 本文将以三个层面展开: TDK优化 网站质量 SEO手段(10种手段) ❄️ 一、TDK优化 TDK是Title(页面标题)、Meta Description(页面描述)和Meta Keywords(页面关键词)的缩写,对网站的这三个信息的提炼是网站SEO的重要环节。 但是由于一些原因,各大主流搜索引擎基本都已经大大降低甚至移除了 <keywords> 对排名的影响。例如: 百度:几乎放弃了对标签的参考价值。参考:百度官方称:keywords这个meta标签已经被丢进历史垃圾堆了; 谷歌:目前几乎已经不考虑这个标签对于SEO的作用了,它可能更侧重于内容的相关性以及反向链接的考量。参考:# Google 不会将关键字元标记用于网页排名 必应:目前 keywords 标签仍然对排名有一定影响; (一)title标签-网站名片 title标签相当于网站的名片,他会直接显示在搜索结果中。一个好的标题势必可以为网站带来流量,从而提升网站排名。 注意:网站标题避免冗长 例如:<title>掘金</title> (二)META标签-网站信息 META标签是网页head区的辅助性标签,它的作用是经过配置一些参数用以描述页面属性。目前几乎所有搜索引擎都使用网上机器人自动查找meta值来给网页分类。 2.1 meta标签如何使用 meta标签的属性有两种:name和http- equiv。 🍀 “name"属性有以下配置项: Keywords(关键词,现在不再重要了):逗号分隔的关键词列表(告诉搜索引擎页面是与什么相关的); description(网站内容描述,很重要):页面描述。搜索引擎会把这个描述显示在搜索结果中; format-detection:格式检测,比如禁止识别电话,邮箱等; author:作者的名字; Robots:用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引; theme-color:网站主题色; <meta name="keywords" content="掘金,稀土,Vue.js,前端面试题,Kotlin,ReactNative,Python"> <meta name="description" content="掘金是面向全球中文开发者的技术内容分享与交流平台。我们通过技术文章、沸点、课程、直播等产品和服务,打造一个激发开发者创作灵感,激励开发者沉淀分享,陪伴开发者成长的综合类技术社区。"> <meta name="format-detection" content="telephone=no"> <meta name="author" content="cece"> <Meta name="Robots" Content="Nofollow"> /** all:文件将被检索,且页面上的链接可以被查询; none:文件将不被检索,且页面上的链接不可以被查询;(和 "noindex, no follow" 起相同作用) index:文件将被检索;(让robot/spider登录) follow:页面上的链接可以被查询; noindex:文件将不被检索,但页面上的链接可以被查询;(不让robot/spider登录) nofollow:文件将不被检索,页面上的链接可以被查询。(不让robot/spider顺着此页的连接往下探找) */ <meta name="theme-color" content="#4285f4" /> 🍀 “http- equiv"属性有以下配置项: ...

November 5, 2024

预处理器

前言 花样不断的前端,貌似多技术方案并行,已经成了家常便饭。 从大的框架开始,已经分裂react与vue派系。两者思维上虽然有相互不断的借鉴,但在大的方向思维上却是截然不同。而在react与vue的竞争以及相互较量的过程中,往往把其他的对手都干倒了,现在市场angular,jQuery等都逐步没落。 预编译css也同样,曾经也有多个派系。而后在sass与less的不断竞争中,stylus等其他的编译器也逐步退出市场。本文的重点,对比预编译css,scss与less对比。 基本介绍 先一起看看官方是如何定义或者介绍他们。 Sass 官方定义: Sass是一种基于Ruby的CSS预处理器,它可以扩展CSS语言,并添加许多其他功能,如变量、嵌套规则、Mixin、函数等。Sass文件以“.scss”扩展名保存,与标准CSS文件兼容,并且可以使用普通CSS代码和语法。Sass也有一个较早的语法格式,以“.sass”扩展名保存,使用缩进的语法来代替括号和分号,但它现在已经不那么流行了。 个人理解: sass是第一个流行的CSS预处理器,在2006年产生,这也为后续他用户量第一埋下伏笔。 Scss 官方定义: Scss也是一种基于Ruby的CSS预处理器,它与Sass有很多相似之处,但是它的语法更接近标准CSS,使用花括号和分号。它是一种非常流行的CSS预处理器,与Sass相比,它更容易学习和使用,并且与现有的CSS代码更兼容。 个人理解: Scss是Sass的一种语法格式,由2007推出。这还要从sass的规范语法说起,最典型的就是Sass使用缩进来表示代码块。这使部分使用者比较别扭。而产生了Scss,基于花括号和分号的CSS语法格式,使得它更易于阅读和理解。随着时间的推移,Scss逐渐取代了Sass作为Sass的主要语法格式。 Less 官方定义: Less是一种基于JavaScript的CSS预处理器,它与Sass和Scss有很多相似之处,但它使用类似CSS的语法,并且更容易学习和使用。Less支持变量、Mixin、嵌套规则等功能,并且可以在客户端和服务器端使用。 个人理解: Less由2009推出,也是提供了一套完整的生态链。它的语法跟sass不同。Less的学习成本更低,更容易理解和编写。此外,Less的编译速度比Sass更快。 Stylus 官方定义: Stylus是一种基于JavaScript的CSS预处理器,它与Less、Sass和Scss有很多相似之处,但它的语法非常灵活,可以自由选择使用缩进或花括号来表示嵌套和块。Stylus还支持变量、Mixin、函数等功能,并且具有非常强大的插件系统,可以轻松地扩展其功能。 个人理解: Stylus也是曾经一个比较完善的预编译语言。 但市场份额却原来越少。个人的观点,一是的学习成本高一些,有入门的门槛。而是生态链的问题,sass跟less的有较完善的生态链,而Stylus更像一个独立的东西。 PostCSS 官方定义: PostCSS不是一种独立的CSS预处理器,而是一个CSS处理工具集合,可以通过各种插件扩展其功能。PostCSS可以用于转换CSS语法、提供自动前缀、压缩CSS代码、处理嵌套规则、优化图片等。它不像其他预处理器那样提供自己的语言,而是基于现有的CSS语法。使用PostCSS可以通过插件来实现更多的自定义和灵活性,使其成为一个强大的CSS处理工具。 个人理解: 跟上述的其他的处理器不同,PostCSS不应该算是一个预处理器,但却是我们做适配,压缩等处理时的一个选择。 数据分析 市场占有率分析 我们借助npm官网统计工具对比,查看less与scss的数据量对比: 链接: npm-stat.com/charts.html… npm-stat.com/charts.html… 如上图,左侧为less的数据,右侧为scss的数据。 我们可以通过统计清晰的看到。单单一个sass的下载量,基本达到less的两倍以上。此处还不包含sass阵营的其他工具,包括node-scss,dart-scss的下载量。 可以得出结论:sass的使用量约为less的几倍。(但此处有个值得一提的地方:统计为全球的用户量的统计,并非针对国内) 组件库选择分析 从上述的数据中,我们了解到sass的使用量较多,但是国内出名的组件库,却是less居多。毕竟组件库,也代表我们的使用习惯之一。我们一起看看组件库的选择。 ant design 选择了Less,地址:www.antdv.com/docs/vue/cu… element 选择了scss,地址:element.eleme.io/#/zh-CN/com… varlet 选择了Less,地址:varlet.gitee.io/varlet-ui/#… vant 选择了Less,地址:vant-contrib.gitee.io/vant/v3/#/z… 结论:关于组件库的选择,Less还是占大多数,当然Scss也是部分组件库的选择。 个人分析 相同点 都属于css语法编译的工具。 工具提供的方法也很多雷同。如都支持嵌套,都支持混合器(Mixin),都支持扩展(Extend),都支持颜色函数,都支持变量等等。 生态链都一致丰富,常用构建工具都基本支持,如webpack,vite, rollup等。 社区支持都强,提供了大量的插件、工具和资源,可以帮助开发者更好地使用Sass。 目的性也一致,都提高了CSS编写的效率和可维护性而产生。 不同点 部分语法不同,如Sass 和 SCSS 中的变量使用 $ 符号进行定义和引用,而不是 Less 中使用的 @ 符号 Sass 和 Scss 还提供了一些 Less 没有的特性,例如控制流语句和继承等。 Sass 和 Scss 是基于Ruby或者Dart,Node的预处理器,他需要借助机器安装这些环境来支持。而Less, 是基于JavaScript的CSS预处理器,引入一段JS即可编译,有浏览器还是服务端,他都能编译。 虽然都有强大的社区,生态链。但总体还是Scss更丰富一些。 特性分析 Node-Sass 在国内有一定的兼容性问题,但是基于Dart 语言编写的 Dart Sass以及解决了这个问题。还在使用Node-Sass的建议切换Dart Sass。 Less 的语法相对于 Sass 更加简洁,易于学习和理解。这使得 Less 在国内开发者中更受欢迎,尤其是对于那些不太熟悉预处理器语言的开发者来说。 Sass的阵营更丰富,使用量更高一些,市场份额也更加稳定。除了发家早,这也得益于生态圈,例如 Bootstrap、Foundation、Bulma、Vue.js 等,都在曾经的版本自带了Sass。 国内组件库,还是Less居多,很多"高级前端", 都觉得less 一直都比 sass 要稳定。至少不会出现Node版本,Python版本不一致等问题。 结语 所以Sass与Less谁更强?估计短期还是分不出成败。 ...

October 10, 2024

Vue3 API

📍前言 最近在一次理解vue项目的代码时,发现周一对好多API都不太熟悉。这间接导致的问题是,代码理解速度要比平常要慢很多。于是乎,赶忙把vue API的学习提上了日程。 在下面的文章中,将地板式地扫盲vue3文档中API模块的所有内容,融入周一的理解进行深入介绍。下面就来一起看看吧~🍬 一、🖇框架搭建 1、关于文档 首先附上官方文档的具体材料:cn.vuejs.org/api/ 2、VUE3 API整体盘点 在vue3的全新API中,有部分在vue2的基础上沿用了。还有另外一部分,是vue3所新增加的。我们先来看vue3 API文档主要包含哪些内容? vue3 API主要包含以下六个部分: 全局API —— 全局会用到的API 组合式API —— vue3所拥有的组合式API 选项式API —— vue2所拥有的选项式API 内置内容 —— 指令、组件、特殊元素和特殊属性 单文件组件 —— 语法定义、 进阶API —— 渲染函数、服务端渲染、TS工具类型和自定义渲染 下面将依据上面提到的六大点内容,来进行相应的剖析和讲解。 二、🎨全局API vue3的全局API包含两个部分:应用实例和通用API。那它们各自都有哪些内容呢? 1、应用实例 2、通用API 三、🚲组合式API 谈到vue3 ,相信大家最为熟悉的就是 composition API 了,也就是 组合式 API 。那么,vue3 的 组合式 API 都给我们带来了什么呢? 1、setup 2、响应式:核心 3、响应式:工具函数 4、响应式:进阶 5、生命周期钩子 6、依赖注入 四、🌠选项式API 选项式API 即 options API 。可能有的小伙伴会觉得它在 vue2 项目下会更为常见一些。但在 vue3 项目中,也是有一些 选项式API 值得我们去挖掘的。那都有哪些内容呢,我们来一探究竟。 ...

October 5, 2024

数组常用方法

数组是 js 中最常用到的数据集合,其内置的方法有很多,熟练掌握这些方法,可以有效的提高我们的工作效率,同时对我们的代码质量也是有很大影响。 一、创建数组 1.使用数组字面量表示法 var arr4 = []; //创建一个空数组 var arr5 = [20]; // 创建一个包含1项数据为20的数组 var arr6 = ["lily","lucy","Tom"]; // 创建一个包含3个字符串的数组 2.使用 Array 构造函数 无参构造 var arr1 = new Array(); //创建一个空数组 带参构造 如果只传一个数值参数,则表示创建一个初始长度为指定数值的空数组 var arr2 = new Array(20); // 创建一个包含20项的数组 如果传入一个非数值的参数或者参数个数大于 1,则表示创建一个包含指定元素的数组 var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组 var array4 = new Array('23'); // ["23"] 3.Array.of 方法创建数组(es6 新增) ES6 为数组新增创建方法的目的之一,是帮助开发者在使用 Array 构造器时避开 js 语言的一个怪异点。 Array.of()方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型。 let arr = Array.of(1, 2); console.log(arr.length);//2 let arr1 = Array.of(3); console.log(arr1.length);//1 console.log(arr1[0]);//3 let arr2 = Array.of('2'); console.log(arr2.length);//1 console.log(arr2[0]);//'2' 4.Array.from 方法创建数组(es6 新增) 在 js 中将非数组对象转换为真正的数组是非常麻烦的。在 ES6 中,将可迭代对象或者类数组对象作为第一个参数传入,Array.from()就能返回一个数组。 function arga(...args) { //...args剩余参数数组,由传递给函数的实际参数提供 let arg = Array.from(args); console.log(arg); } arga('arr1', 26, 'from'); // ['arr1',26,'from'] 映射转换 如果你想实行进一步的数组转换,你可以向 Array.from()方法传递一个映射用的函数作为第二个参数。此函数会将数组对象的每一个值转换为目标形式,并将其存储在目标数组的对应位置上。 ...

November 8, 2024

CSR,SSR和SSG

SPA、MPA、SSR 和 CSR 这几个词可能在你的工作生涯中经常出现,网上相关文章也很多。如果你对这些概念感到模糊或完全不了解,希望本文能帮助你理解这些渲染模式。 SPA 与 MPA MPA MPA(multiple page application) 称为多页应用, 指的是有多个页面的应用,从技术手段上来讲,你可以这么粗略地理解。 首屏速度快:各个页面相互独立,需要单独维护多个 html 页面,每个请求都直接返回 html。 切换页面比较慢:基于原生浏览器的文档跳转(navigating across documents)。因此每一次的页面更新都是一次页面重载,这将带来巨大的重启性能消耗。 对 SEO 友好:页面在初始时,就具有全部的页面内容而非 「无状态」,从而达到更好的收录效果。 SPA SPA(single page application)称为单页应用。通过 js 去感知到 url 的变化,动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上。此时的路由不是后端来做了,而是前端来做,动态显示需要的组件。 页面切换速度快:路由跳转是基于特定的实现(如 vue-router,react-router 等前端路由),而非原生浏览器的文档跳转,避免了不必要的整个页面重载。 前后端分离:基于前端路由,SPA 与应用后端解耦,使得前端不再依赖于后端的路由分配。 首屏时间慢:首屏除了 html 还要额外请求并执行 js 文件,通过 js 在空页面上渲染首屏。 SEO 不友好:内容都是靠 js 渲染生成出来的,但搜索引擎并不识别这部分内容,导致 SEO 效果差 CSR(Client Side Rendering) CSR(客户端渲染)是一种在浏览器上执行 JavaScript 以生成 DOM 并显示内容的渲染方法。CSR 更贴近现代前端开发,我们通常使用的 Vue 和 React 默认使用 CSR。其大致流程如下: 浏览器向前端服务器请求 html 和 js html 页面为空,初始加载不显示任何内容,通过执行 js 渲染内容 通过后端暴露的 API 进行交互 对于典型的 CSR 应用程序,浏览器仅接收一个用作应用程序容器的 HTML 页面,因此也称为单页应用,所以 CSR 的特点与之前提到的 SPA 类似。 ...

November 5, 2024

架构

前言 在项目中经常存在如下问题: 1.模块拆分不合理 2.变量和函数命名不知所云 3.缺少注释或者是写了一堆描述不清的内容 4.重复的代码遍布各个角落等 因为这些不良的编程习惯,导致了项目越来越难以维护,程序性能越来越低,大大降低了日常的工作效率以及提高了公司的开发成本。 下面就以CSS在Vue3项目中的架构为切入点,通过减少CSS代码的冗余度和增强CSS代码的维护性、扩展性来提高我们的编程能力和项目架构能力。 CSS的设计模式 在学习CSS架构之前,我们先简单看一下常见的5种CSS设计模式,这些设计模式都为我们的CSS架构提供了一定的开发思路。 1.OOCSS模式 OOCSS(Object-Oriented CSS)字面意思是面向对象的CSS,在开发中它有如下的规范约定 减少对 HTML 结构的依赖 # bad # 1.匹配效率低,影响css性能 # 2.和html耦合度高,维护性和扩展性低 .container-list ul li a {} <div class="container-list"> <ul> <li> <a>...</a> </li> </ul> </div> # good .container-list .list-item {} <div class="container-list"> <ul> <li> <a class="list-item">...</a> </li> </ul> </div> 增加样式的复用性 .label { # 公共代码 } .label-danger { # 特定代码 } .label-info { # 特定代码 } <div> <p class="label label-danger"></p> <p class="label label-info"></p> </div> 2.BEM模式 BEM 是进阶版的OOCSS,是一个分层系统,它把我们的网站分为三层,这三层正好对应着 BEM 三个英文单词的简写 block, element, modifier,分为为 块层、元素层、修饰符层。 ...

October 10, 2024

响应式原理

什么是响应式系统 在 Vue 中,数据驱动视图是一个非常重要的概念。当数据发生变化时,视图会自动更新,这是因为 Vue 实现了一个响应式系统,通过追踪依赖关系来自动更新视图。 简单来说,响应式系统就是 Vue 能够监听数据变化,并在变化时自动更新 DOM 的核心机制。在 Vue3 中,响应式系统的改进使得响应式数据可以更加高效地更新视图,同时也提升了开发体验和性能。 Vue2 的响应式原理 在 Vue2 中,响应式原理是通过 Object.defineProperty 来实现的。Vue 会在数据对象上定义 getter 和 setter,来实现数据变化时更新视图的功能。 举个例子,当一个数据对象被定义为响应式时,我们可以通过访问这个对象的属性来触发 get 操作。具体实现如下: Object.defineProperty(obj, 'foo', { get: function() { console.log('get foo') return obj._foo }, set: function(newVal) { console.log('set foo') obj._foo = newVal } }) 在上面的代码中,我们通过 Object.defineProperty 方法来监听对象上的属性 foo,当访问 foo 属性时,会触发 get 操作,并输出日志。同理,当给 foo 属性赋值时,会触发 set 操作,并输出日志。 在 Vue2 中,我们可以通过使用上面的方法来将数据对象中的所有属性转化成响应式的,以实现数据变化时更新视图的功能。 Vue3 的响应式原理 在 Vue3 中,响应式原理的实现方式和 Vue2 相比,有了相当大的变化。Vue3 直接使用了 ES6 Proxy 对象来拦截对对象的访问操作。Proxy 可以监听到对对象进行的访问、赋值等操作,并在这些操作发生时通知相关依赖以维护响应式系统的更新。 ...

October 5, 2024

浏览器解析 HTML 文件

1. 什么是浏览器解析和渲染HTML 一句话概括:将html代码转换成页面上显示的内容。 表1:形象展示将HTML转换成页面上显示的内容 2. 浏览器解析和渲染HTML过程? 那么浏览器拿到HTML代码后是如何把其转换成页面上显示的内容的? 2.1 宏观描述执行过程 2.1.1 解析和渲染 首先我们来看两个概念,解析和渲染,确切来说是DOM解析和DOM渲染。 DOM解析: 生成DOM tree的过程。就是把你所写的各种html标签,生成一个DOM tree,可以认为就是生成了一个最原始的页面,一点样式都没有,毫无CSS修饰。 DOM渲染: 将DOM tree与css样式结合,生成Render tree,并将其呈现在浏览器页面上。浏览器会把本身默认的样式+用户自己写得样式整合到一起,形成一个CSS tree,而DOM渲染就是指DOM tree 和CSS tree 结合到一起,生成一个Render tree,呈现出一个带有样式的页面。 这里需要注意,DOM解析和DOM渲染由两个不同的线程来完成的,简单说就是二者可以并行进行。 DOM解析通常是由浏览器的主线程来完成的。DOM渲染是由浏览器的渲染线程来完成的。 分离解析和渲染的这种设计使得浏览器能够在解析 HTML 文档的同时将页面渲染到屏幕上,这样用户就能够更快地看到完整的页面了。 2.1.2 宏观描述执行过程 补充了解析和渲染的概念,我们来看看浏览器具体是如何把其转换成页面上显示的内容的。其过程大致分为下图的四步。 图1:浏览器解析和渲染HTML的过程 第一步:将载入的HTML文件解析成DOM树(DOM tree),并且将各个标记标识解析成DOM树的各个节点;在解析HTML的同时会将CSS样式解析成CSS规则(CSS rules)。 第二步:将解析成的DOM树和CSS规则进行关联生成渲染树(Render tree)。 第三步:进入布局阶段,为DOM树的每个节点分配在屏幕上出现的确切坐标(这一阶段还是渲染树) 第四步:进入绘制阶段,在这里渲染引擎的工作就结束了,接下来就给用户界面后端(UI Backend)对渲染树的每个节点进行绘制,呈现出页面效果。 2.2 细化执行过程 2.2.1 顺序执行 dom解析过程是从上向下,顺序执行的。顺序执行的意思是一行一行的执行,上一行执行完再执行下一行。 <h1>1<h1> <h1>2<h1> <h1>3<h1> <script></script> <style></style> <!-- 先1,再2,再3,按顺序解析。 --> 2.2.2 渐进式 浏览器是渐进式渲染,即边解析边渲染。通俗的说就是,这一行代码解析完,就可以在浏览器的页面渲染展示出来。因为浏览器的解析和渲染由两个不同线程来完成,所以可以实现边解析边渲染。 <h1>1</h1> <script>debugger</script> <h1>2</h1> <script>debugger</script> <h1>3</h1> <!-- 先解析渲染出1,再debugger;再解析渲染出2,再debugger;最后解析渲染出3 --> 2.3 问题:css、js会阻塞解析和渲染吗? 这部分内容可参考这篇掘金内容,内含测试代码:关于 JS 与 CSS 是否阻塞 DOM 的渲染和解析 - 掘金 ...

November 5, 2024