html相关面试题

html相关面试题

1.html和css中的图片加载与渲染规则是什么样的?

  1. 图片的加载时机:当浏览器解析 HTML 页面或 CSS 样式表时,会遇到 `` 标签或 background-image 属性指定的图片路径。浏览器会开始从服务器请求这些图片资源,并进行加载。
  2. 图片加载顺序:通常,按照 HTML 文档的从上到下顺序加载。也就是说,先加载文档中出现的第一个图片,然后是第二个,以此类推。CSS 中的背景图片根据样式表的顺序进行加载。
  3. 图片并行加载:现代浏览器通常支持并行加载多个图片,提高加载速度。这意味着可以同时请求和加载多张图片而无需等待前一张图片完全加载完成。具体并行加载的数量限制因浏览器而异。
  4. 图片渲染方式:
    • 在 DOM 中的 `` 元素加载完成后,该图片将自动进行渲染,显示在网页中。
    • 背景图片(通过 CSS background-image 属性设置)在它们的父元素可见时会开始加载,并在加载完成后进行渲染。
  5. 替代文本(Alternate Text):如果图片加载失败或不可用(例如图片路径错误),浏览器会显示替代文本(由 `` 的 alt 属性定义)或显示一个空白区域。
  6. 响应式图片:使用 CSS 的媒体查询和 srcset 属性可以实现根据屏幕大小加载不同尺寸的响应式图片。这可以提高页面的性能和适应性。

以上是图片在 HTML 和 CSS 中加载和渲染的基本规则。通过优化图片大小、格式选择、懒加载等技术可以进一步提升网页加载速度和用户体验。

2.title与h1的区别、b与strong的区别、i与em的区别?

title 和 h1 的区别

  1. 用途不同:title 标签用于定义 HTML 文档的标题,通常会显示在浏览器的标签页上或者窗口的标题栏上,对于搜索引擎优化(SEO)也非常重要。而 h1 标签用于表示文档的主标题,通常显示在页面内容区域的顶部。
  2. 所在位置不同:title 标签应该放在 标签内,而 h1 标签则应该放在 标签内。
  3. 格式和样式不同:title 标签中的文本通常比较短,并且不需要进行格式化、排版等操作;而 h1 标签中的文本通常比较长,并且需要进行合适的格式化、排版和样式设置,以便使其适应页面布局和设计风格。

b 和 strong 的区别

b 标记用于指定文本加粗的外观效果,通常只是为了强调关键词或短语,没有特别强的语义化含义。而 strong 标记则表示文本的强调重点,具有更强的语义化含义,并且可以改变文本的语调和读音等方面。

i 和 em 的区别

i 标记用于指定文本斜体的外观效果,通常只是为了强调关键词或短语,没有特别强的语义化含义。而 em 标记则表示文本的重要性,具有更强的语义化含义,并且可以改变文本的语调和读音等方面。

最后

需要注意的是,在 HTML5 中,b 和 i 标记已经被废弃,推荐使用 strong 和 em 标记来代替。同时,随着搜索引擎的发展和语义化网页的兴起,h1-h6 标记也被赋予了更重要的语义化含义,应该根据具体情况来选择使用不同的标记。

3.script 标签为什么建议放在 body 标签的底部(defer、async)?

因为浏览器在渲染html的时候是从上到下执行的,当遇到js文件的时候就会停止当前页面的渲染,转而去下载js文件。如果将script标签放在头部,在文件很大的情况下将导致首屏加载时间延长,影响用户体验。

4.说说你对 SSG 的理解?

SSG(Static Site Generation,静态网站生成)是指在构建时预先生成静态页面,并将这些页面部署到 CDN 或者其他存储服务中,以提升 Web 应用的性能和用户体验。

具体来说,SSG 的实现方式通常包括以下几个步骤:

  1. 在开发阶段,使用模板引擎等技术创建静态页面模板;
  2. 将需要展示的数据从后台 API 中获取或者通过其他渠道获取,并将其填充到静态页面模板中,生成完整的 HTML 页面;
  3. 使用构建工具(例如 Gatsby、Next.js 等)对静态页面进行构建,生成静态 HTML、CSS 和 JavaScript 文件;
  4. 部署生成好的静态文件到服务器或者 CDN 上,以供用户访问。

相比于传统的动态网页,SSG 具有如下优势:

  1. 加载速度快:由于不需要每次请求都动态地渲染页面,SSG 可以减少页面加载时间,从而提高用户体验和搜索引擎排名;
  2. 安全性高:由于没有后台代码和数据库,SSG 不容易受到 SQL 注入等攻击;
  3. 成本低:由于不需要动态服务器等设备,SSG 可以降低网站的运维成本和服务器负担。

需要注意的是,SSG 不适用于频繁更新的内容和动态交互等场景,但对于内容较为稳定和更新较少的网站则是一个性能优化的好选择。

5.跨域时怎么处理 cookie?

  1. 使用 withCredentials 属性:在发送跨域请求时,将 XMLHttpRequest 对象的 withCredentials 属性设置为 true,表示允许发送和接收包含凭证(Cookie、HTTP认证等)的请求。服务器端也需设置响应头 Access-Control-Allow-Credentials: true,确保响应中包含 Set-Cookie 头信息。需要注意的是,对于简单请求(比如 GET、POST),服务器端的响应头不能包含除了基本字段之外的其他自定义字段,否则浏览器会返回错误。
javascript复制代码const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('GET', 'http://example.com/api', true);
xhr.onreadystatechange = function() {
  if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
    // 请求成功处理逻辑
  }
};
xhr.send();
  1. 设置响应头 Access-Control-Allow-Origin :服务器端需要设置响应头 Access-Control-Allow-Origin,指定允许请求的源。可以设置为具体的域名,或使用通配符 * 表示允许任意域名请求。同时需要设置 Access-Control-Allow-Credentials: true 表示允许携带凭证。
  2. 域名代理:可以通过配置一个代理服务器,在代理服务器上转发请求并携带 Cookie。客户端向代理服务器发送请求,代理服务器再将请求转发给目标服务器,并在转发时携带 Cookie。这样实现了间接跨域,使得客户端在与代理服务器通信时可以携带 Cookie,而实际上请求还是在同源下进行的。

6.什么是HTML5,以及和HTML的区别是什么?

HTML5是HTML的新标准,其主要目标是无需任何额外的插件如Flash、Silverlight等,就可以传输所有内容。它囊括了动画、视频、丰富的图形用户界面等。

HTML5是由万维网联盟(W3C)和 Web Hypertext Application Technology Working Group 合作创建的HTML新版本。

区别

从文档声明类型上看:

HTML是很长的一段代码,很难记住。如下代码:

1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">

HTML5却只有简简单单的声明,方便记忆。如下:

<!DOCTYPE html>

从语义结构上看:

  • HTML4.0:没有体现结构语义化的标签,通常都是这样来命名的 ``,这样表示网站的头部。
  • HTML5:在语义上却有很大的优势。提供了一些新的标签,比如:``。

拓展

不输入,浏览器将无法识别html文件,因此html将无法正常工作。

7.说说你对 Dom 树的理解?

什么是 DOM

从网络传给渲染引擎的 HTML 文件字节流是无法直接被渲染引擎理解的,所以要将其转化为渲染引擎能够理解的内部结构,这个结构就是 DOM。

DOM 提供了对 HTML 文档结构化的表述。

在渲染引擎中,DOM 有三个层面的作用:

  • 从页面的视角来看,DOM 是生成页面的基础数据结构。
  • 从 JavaScript 脚本视角来看,DOM 提供给 JavaScript 脚本操作的接口,通过这套接口,JavaScript 可以对 DOM 结构进行访问,从而改变文档的结构、样式和内容。
  • 从安全视角来看,DOM 是一道安全防护线,一些不安全的内容在 DOM 解析阶段就被拒之门外了。

简言之,DOM 是表述 HTML 的内部数据结构,它会将 Web 页面和 JavaScript 脚本连接起来,并过滤一些不安全的内容。

DOM树如何生成

HTML 解析器(HTMLParser): 负责将 HTML 字节流转换为 DOM 结构。

那么网络进程是如何将数据传给HTML解析器的呢?
在这里插入图片描述
预览

从图中我们可以知道,网络进程和渲染进程之间有一个共享数据通道,网络进程加载了多少数据, 就将数据传给HTML解析器进行解析。

HTML解析器接收到数据(字节流)之后,字节流将转化成DOM,过程如下:
在这里插入图片描述

预览

有三个阶段

1、通过分词器将字节流转化为Token。 分词器先将字节流转换为一个个 Token,分为 Tag Token 和文本 Token。

注意,这里的Token并不是我们之前理解的Token,这里就是一个片段。

2、Token解析为DOM节点。

3、将 DOM节点添加到DOM树中。

JavaScript影响DOM的生成

我们知道,JavaScript可以修改DOM,它也会影响DOM的生成。

1、内嵌 JavaScript 脚本 比如我们嵌入了一段``标签的代码,之前的解析过程都一样,但是解析到script标签时, 渲染引擎判断这是一段脚本,此时 HTML 解析器就会暂停 DOM 的解析, 因为接下来的 JavaScript 可能要修改当前已经生成的 DOM 结构。

暂停解析之后,JavaScript 引擎介入,并执行``标签中的这段脚本。 脚本执行完成之后,HTML 解析器恢复解析过程,继续解析后续的内容,直至生成最终的 DOM。

2、引入 JavaScript 文件 基本上跟之前是一致的,不同点在于,暂停解析之后执行JavaScript 代码,需要先下载这段 JavaScript 代码

8.导致页面加载白屏时间长的原因有哪些,怎么进行优化?

一、白屏时间

白屏时间:即用户点击一个链接或打开浏览器输入URL地址后,从屏幕空白到显示第一个画面的时间。

二、白屏时间的重要性

当用户点开一个链接或者是直接在浏览器中输入URL开始进行访问时,就开始等待页面的展示。页面渲染的时间越短,用户等待的时间就越短,用户感知到页面的速度就越快。这样可以极大的提升用户的体验,减少用户的跳出,提升页面的留存率。

三、白屏的过程

从输入url,到页面的画面展示的过程

1、首先,在浏览器地址栏中输入url

2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。

3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。

4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。

5、握手成功后,浏览器向服务器发送http请求,请求数据包。

6、服务器处理收到的请求,将数据返回至浏览器

7、浏览器收到HTTP响应

8、读取页面内容,浏览器渲染,解析html源码

9、生成Dom树、解析css样式、js交互,渲染显示页面

浏览器下载HTML后,首先解析头部代码,进行样式表下载,然后继续向下解析HTML代码,构建DOM树,同时进行样式下载。当DOM树构建完成后,立即开始构造CSSOM树。理想情况下,样式表下载速度够快,DOM树和CSSOM树进入一个并行的过程,当两棵树构建完毕,构建渲染树,然后进行绘制。

Tips:浏览器安全解析策略对解析HTML造成的影响:

当解析HTML时遇到内联JS代码,会阻塞DOM树的构建,会先执行完JS代码;当CSS样式文件没有下载完成时,浏览器解析HTML遇到了内联JS代码,此时,浏览器暂停JS脚本执行,暂停HTML解析。直到CSS文件下载完成,完成CSSOM树构建,重新恢复原来的解析。

JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的。

四、白屏-性能优化

1. DNS解析优化

针对DNS Lookup环节,我们可以针对性的进行DNS解析优化。

  • DNS缓存优化
  • DNS预加载策略
  • 稳定可靠的DNS服务器
2. TCP网络链路优化

多花点钱吧

3. 服务端处理优化

服务端的处理优化,是一个非常庞大的话题,会涉及到如Redis缓存、数据库存储优化或是系统内的各种中间件以及Gzip压缩等…

4. 浏览器下载、解析、渲染页面优化

根据浏览器对页面的下载、解析、渲染过程,可以考虑一下的优化处理:

  • 尽可能的精简HTML的代码和结构
  • 尽可能的优化CSS文件和结构
  • 一定要合理的放置JS代码,尽量不要使用内联的JS代码
  • 将渲染首屏内容所需的关键CSS内联到HTML中,能使CSS更快速地下载。在HTML下载完成之后就能渲染了,页面渲染的时间提前,从而缩短首屏渲染时间;
  • 延迟首屏不需要的图片加载,而优先加载首屏所需图片(offsetTop<clientHeight)
1document.documentElement.clientHeight//获取屏幕可视区域的高度
2element.offsetTop//获取元素相对于文档顶部的高度

因为JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞 JavaScript 的执行,所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件,使用不当会影响到页面性能的。

9.渐进式jpg有了解过吗?

渐进式 JPEG(Progressive JPEG),即PJPEG,是该标准的三种流行压缩模式之一。

渐进式 JPEG 以特定方式压缩照片和图形,与基线 JPEG 不同,PJPEG 在 Web 浏览器中呈现时,会首先给出模糊图像的外观。然后一点一点地开始图片渲染,直到它显示完全渲染的图像。浏览器实际上是逐行解释图像,但在占位符中提供了完整图像的模糊预览。随着 Web 浏览器的渲染引擎处理数据,图像的对比度开始变得更清晰、更详细。直到最后渲染完毕,用户将看到完整的清晰图像。

PJPEG 能够起到一种很有意义的心理效果,让用户有东西可看,而不必坐着干等大型图像慢慢显示在屏幕上。

PJPEG 适用于大部分常用的浏览器,包括 ChromeFirefoxInternet Explorer 9 及更高版本。旧版本的 Internet Explorer 在显示渐进式 JPEG 时存在一些问题,不过这只是很小一部分用户。而不支持渐进式 JPEG 格式的浏览器会像普通 JPEG 一样加载照片。

10.假设我要上传图片,怎么在选择图片后,通过浏览器预览待上传的图片?

实现预览有两种方式:

  • 一种是用 window.URL.createObjectURl 方法对选择的图片数据(可以勉强理解为input的value)生成一个blob对象路径
  • 第二种是使用 FileReader 读取器

那么无论那种方法,首先都得得到文件数据,获得文件数据是从files集合中获取。

先来看下 window.URL.createObjectURl 的实现方法:

1function imgChange(img) {
2 document.querySelector("img").src=window.URL.cteateObejectURL(img.files[0]);
3}

而使用 FileRader 读取文件.可分为四步;

  1. 创建 FileReader 对像;
  2. 调用 readAsDataURL 方法读取文件;
  3. 调用 onload 事件监听。因为我们需要拿到完整的数据,但我们又不知道文件何时读完,所以需要第三步监听;
  4. 通过 FileReaderresult 属性拿到读取结果。
复制1function imgChange(img) {
2    // 生成一个文件读取的对象
3    const reader = new FileReader();
4    reader.onload = function (ev) {
5        document.querySelector("img").src = imgFile;
6    }
7    //发起异步读取文件请求,读取结果为data:url的字符串形式,
8    reader.readAsDataURL(img.files[0]);
}

11.SPA应用怎么进行SEO?

SPA全名是Single Page Application,指的是单页面应用。

SEO全称为Search Engine Optimization,指的是搜索引擎优化。

SPA技术将产出html的逻辑从服务器转移到了客户端,在进入React, Vue等UI框架进行开发时,我们开发的页面更多的是在客户端进行脚本执行、数据请求和UI动态装载。

那么搜索引擎爬虫在抓取这样的页面的时,在未做任何优化的情况下,通常拿到的是类似下面的字符文本:

1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4    <meta charset="UTF-8">
5    <title>title</title>
6</head>
7<body>
8<div id="root"></div>
9<script src="index.js"></script>
10</body>
11</html>

除了可以事先定义的title(可能title也不能事先确定),在SPA下很多内容需要通过ajax请求server拿到数据通过脚本执行产生。通常爬虫不会有类似浏览器的执行环境去产生这些内容。

那么如何让爬虫拿到的数据和用户通过浏览器看到的数据尽量是一致?

SPA的优缺点

优点:用户体验好,前后端代码分离,利于后期的维护

缺点:seo不好,首次加载时长比较久,导航需要自己去实现前进后退。

SPA如何解决SEO的问题

  • SSR 服务端渲染

优点:首屏加载快(因为服务器返回的网页已经包含数据, 所以之下载完JS/CSS就可以直接渲染)。每次请求返回的都是一个独立完成的网页, 更利于SEO。

缺点就是服务器压力会比较大,对网络要求比较大,

预渲染

无需服务器实时动态编译,采用预渲染,在构建时针对特定路由简单的生成静态HTML文件

本质就是客户端渲染, 只不过和SPA不同的是预渲染有多个界面

最大优点: 由于有多个界面, 所以更利于SEO

最大缺点: 首屏加载慢, 预编译会非常的慢

12.如何实现SEO优化?

一、内部优化

  • META 标签优化:例如:TITLE,KEYWORDS,DESCRIPTION (TDK)等的优化
  • 内部链接的优化,包括相关性链接(Tag 标签),锚文本链接,各导航链接,及图片链接
  • 网站内容更新:每天保持站内的更新(主要是文章的更新等)
  • 服务器端渲染(SSR)

二、外部优化

  • 外部链接类别:博客、论坛、B2B、新闻、分类信息、贴吧、知道、百科、相关信息网等尽量保持链接的多样性
  • 外链运营:每天添加一定数量的外部链接,使关键词排名稳定提升。
  • 外链选择:与一些和你网站相关性比较高,整体质量比较好的网站交换友情链接,巩固稳定关键词排名

13.seo是什么?

SEO(Search Engine Optimization),汉译为搜索引擎优化。

搜索引擎优化是一种利用搜索引擎的搜索规则来提高目前网站在有关搜索引擎内的自然排名的方式。

SEO是指为了从搜索引擎中获得更多的免费流量,从网站结构、内容建设方案、用户互动传播、页面等角度进行合理规划,使网站更适合搜索引擎的索引原则的行为。

14.SEO的原理是什么?

爬行和抓取

搜索引擎派出一个能够在网上发现新网页并抓取文件的程序,这个程序通常被称为蜘蛛或机器人。

搜索引擎蜘蛛从数据库中已知的网页开始出发,就像正常用户的浏览器一样访问这些网页并抓取文件。

并且搜索引擎蜘蛛会跟踪网页上的链接,访问更多网页,这个过程就叫爬行。

当通过链接发现有新的网址时,蜘蛛将把新网址记录入数据库等待抓取。

跟踪网页链接是搜索引擎蜘蛛发现新网址的最基本方法,所以反向链接成为搜索引擎优化的最基本因素之一。

没有反向链接,搜索引擎连页面都发现不了,就更谈不上排名了。

搜索引擎蜘蛛抓取的页面文件与用户浏览器得到的完全一样,抓取的文件存入数据库。

索引

搜索引擎索引程序把蜘蛛抓取的网页文件分解、分析,并以巨大表格的形式存入数据库,这个过程就是索引。在索引数据库中,网页文字内容,关键词出现的位置、字体、颜色、加粗、斜体等相关信息都有相应记录。

搜索引擎索引数据库存储巨量数据,主流搜索引擎通常都存有几十亿级别的网页。

搜索词处理

用户在搜索引擎界面输入关键词,单击“搜索”按钮后,搜索引擎程序即对输入的搜索词进行处理,如中文特有的分词处理,对关键词词序的分别,去除停止词,判断是否需要启动整合搜索,判断是否有拼写错误或错别字等情况。搜索词的处理必须十分快速。

排序

对搜索词进行处理后,搜索引擎排序程序开始工作,从索引数据库中找出所有包含搜索词的网页,并且根据排名计算法计算出哪些网页应该排在前面,然后按一定格式返回“搜索”页面。

排序过程虽然在一两秒之内就完成返回用户所要的搜索结果,实际上这是一个非常复杂的过程。排名算法需要实时从索引数据库中找出所有相关页面,实时计算相关性,加入过滤算法,其复杂程度是外人无法想象的。搜索引擎是当今规模最大、最复杂的计算系统之一。

但是即使最好的搜素引擎在鉴别网页上也还无法与人相比,这就是为什么网站需要搜索引擎优化。没有 SEO 的帮助,搜索引擎常常并不能正确返回最相关、最权威、最有用的信息。

15.script标签放在header里和放在body底部里有什么区别?

script 通常被放在 header 或者 body 标签中,但位置的不同对于页面的加载效果也不一样。

demo中引用的js文件,都有延迟3秒才执行完成的设定。

放在 header 中

1<head>
2  <title>script 加载机制</title>
3  <script src='/js/test1.js'></script>
4  <script src='/js/test2.js'></script>
5  <script src='/js/test3.js'></script>
6</head>

img

预览

你能看到 html 第一时间被加载进来,但页面 body 内容迟迟没有渲染出来。因为在等待 header 标签中 script 脚本的加载,3 秒后,整个页面渲染完成。

放在 body 底部

1<body>
2  <h2>script 加载机制</h2>
3  <script src='/js/test1.js'></script>
4  <script src='/js/test2.js'></script>
5  <script src='/js/test3.js'></script>
6</body>

img

预览

这次 html 内容第一时间渲染完成,随后等待 js 的加载。

总结

脚本会阻塞页面的渲染,所以推荐将其放在 body 底部,因为当解析到 script 标签时,通常页面的大部分内容都已经渲染完成,让用户马上能看到一个非空白页面。

另外你能看到多个脚本之间都是异步向服务器请求,他们之间不互相依赖,最终只等待 3 秒,而非 3+3+3 秒。

16.浏览器乱码的原因是什么?如何解决

产生乱码的原因:

  • 网页源代码是gbk的编码,而内容中的中文字是utf-8编码的,这样浏览器打开即会出现html乱码,反之也会出现乱码;
  • html网页编码是gbk,而程序从数据库中调出呈现是utf-8编码的内容也会造成编码乱码;
  • 浏览器不能自动检测网页编码,造成网页乱码。

解决办法:

  • 使用软件编辑HTML网页内容;
  • 如果网页设置编码是gbk,而数据库储存数据编码格式是UTF-8,此时需要程序查询数据库数据显示数据前进程序转码;
  • 如果浏览器浏览时候出现网页乱码,在浏览器中找到转换编码的菜单进行转换。

17.Canvas和SVG有什么区别?

1)SVG: SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言XML描述的2D图形的语言,SVG基于XML就意味着SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

其特点如下:

  • 不依赖分辨率
  • 支持事件处理器
  • 最适合带有大型渲染区域的应用程序(比如谷歌地图)
  • 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
  • 不适合游戏应用

(2)Canvas: Canvas是画布,通过Javascript来绘制2D图形,是逐像素进行渲染的。其位置发生改变,就会重新进行绘制。

其特点如下:

  • 依赖分辨率
  • 不支持事件处理器
  • 弱的文本渲染能力
  • 能够以 .png 或 .jpg 格式保存结果图像
  • 最适合图像密集型的游戏,其中的许多对象会被频繁重绘

注:矢量图,也称为面向对象的图像或绘图图像,在数学上定义为一系列由线连接的点。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。

18.浏览器是如何对 HTML5 的离线储存资源进行管理和加载?

  • 在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问页面 ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过页面并且资源已经进行离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,就会重新下载文件中的资源并进行离线存储。
  • 离线的情况下,浏览器会直接使用离线存储的资源。

19.img的srcset属性的作⽤?

响应式页面中经常用到根据屏幕密度设置不同的图片。这时就用到了 img 标签的srcset属性。srcset属性用于设置不同屏幕密度下,img 会自动加载不同的图片。用法如下:

1<img src="image-128.png" srcset="image-256.png 2x" />

使用上面的代码,就能实现在屏幕密度为1x的情况下加载image-128.png, 屏幕密度为2x时加载image-256.png。

按照上面的实现,不同的屏幕密度都要设置图片地址,目前的屏幕密度有1x,2x,3x,4x四种,如果每一个图片都设置4张图片,加载就会很慢。所以就有了新的srcset标准。代码如下:

1<img src="image-128.png"
2     srcset="image-128.png 128w, image-256.png 256w, image-512.png 512w"
3     sizes="(max-width: 360px) 340px, 128px" />

其中srcset指定图片的地址和对应的图片质量。sizes用来设置图片的尺寸零界点。对于 srcset 中的 w 单位,可以理解成图片质量。如果可视区域小于这个质量的值,就可以使用。浏览器会自动选择一个最小的可用图片。

sizes语法如下:

1sizes="[media query] [length], [media query] [length] ... "

sizes就是指默认显示128px, 如果视区宽度大于360px, 则显示340px。

20.HTML5的离线储存怎么使用,它的工作原理是什么

离线存储指的是:在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。

**原理:**HTML5的离线存储是基于一个新建的 .appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示

使用方法: (1)创建一个和 html 同名的 manifest 文件,然后在页面头部加入 manifest 属性:

1<html lang="en" manifest="index.manifest">

(2)在 cache.manifest 文件中编写需要离线存储的资源:

1CACHE MANIFEST
2    #v0.11
3    CACHE:
4    js/app.js
5    css/style.css
6    NETWORK:
7    resourse/logo.png
8    FALLBACK:
9    / /offline.html
  • CACHE: 表示需要离线存储的资源列表,由于包含 manifest 文件的页面将被自动离线存储,所以不需要把页面自身也列出来。
  • NETWORK: 表示在它下面列出来的资源只有在在线的情况下才能访问,他们不会被离线存储,所以在离线情况下无法使用这些资源。不过,如果在 CACHE 和 NETWORK 中有一个相同的资源,那么这个资源还是会被离线存储,也就是说 CACHE 的优先级更高。
  • FALLBACK: 表示如果访问第一个资源失败,那么就使用第二个资源来替换他,比如上面这个文件表示的就是如果访问根目录下任何一个资源失败了,那么就去访问 offline.html 。

(3)在离线状态时,操作 window.applicationCache 进行离线缓存的操作。

如何更新缓存:

(1)更新 manifest 文件

(2)通过 javascript 操作

(3)清除浏览器缓存

注意事项:

(1)浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。

(2)如果 manifest 文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。

(3)引用 manifest 的 html 必须与 manifest 文件同源,在同一个域下。

(4)FALLBACK 中的资源必须和 manifest 文件同源。

(5)当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。

(6)站点中的其他页面即使没有设置 manifest 属性,请求的资源如果在缓存中也从缓存中访问。

(7)当 manifest 文件发生改变时,资源请求本身也会触发更新。

21.label标签有什么用?

label标签来定义表单控制间的关系。当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

<label for="Name">Number:</label>
<input type='text' name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>

22.如何实现浏览器内多个标签页之间的通信?

Broadcast Channel

顾名思义,“广播频道”,官方文档里的解释为“用于同源不同页面之间完成通信的功能”,在其中某个页面发送的消息会被其他页面监听到。

注意“同源”二字,该方法无法完成跨域的数据传输。

localStorage

localStorage是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session是会话级的存储空间,每个标签页都是单独的)。

SharedWorker

SharedWorker可以被多个window共同使用,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)

WebSocket通讯

全双工(full-duplex)通信自然可以实现多个标签之间的通信

定时器setInterval+cookie

  • 在页面A设置一个使用setInterval定时器不断刷新,检查Cookies的值是否发生变化,如果变化就进行刷新的操作。
  • 由于Cookies是在同域可读的,所以在页面B审核的时候改变Cookies的值,页面A自然是可以拿到的。

这样做确实可以实现我想要的功能,但是这样的方法相当浪费资源。虽然在这个性能过盛的时代,浪费不浪费也感觉不出来,但是这种实现方案,确实不够优雅。

postMessage

两个需要交互的tab页面具有依赖关系。

如 A页面中通过JavaScript的window.open打开B页面,或者B页面通过iframe嵌入至A页面,此种情形最简单,可以通过HTML5的 window.postMessage API完成通信,由于postMessage函数是绑定在 window 全局对象下,因此通信的页面中必须有一个页面(如A页面)可以获取另一个页面(如B页面)的window对象,这样才可以完成单向通信;B页面无需获取A页面的window对象,如果需要B页面对A页面的通信,只需要在B页面侦听message事件,获取事件中传递的source对象,该对象即为A页面window对象的引用:

//B页面
window.addEventListner('message',(e)=>{
    let {data,source,origin} = e;
    source.postMessage('message echo','/');
});

postMessage的第一个参数为消息实体,它是一个结构化对象,即可以通过“JSON.stringify和JSON.parse”函数还原的对象;第二个参数为消息发送范围选择器,设置为“/”意味着只发送消息给同源的页面,设置为“*”则发送全部页面。

23.input上传文件可以同时选择多张吗?怎么设置?

可以,通过给input标签设置multiple属性。

<input type="file" name="files" multiple/>

24.iconfont是什么?有什么优缺点?

什么是 IconFont

顾名思义,IconFont 就是字体图标。严格地说,就是一种字体,但是,它们不包含字母或数字,而是包含符号和字形。您可以使用 CSS 设置样式,就像设置常规文本一样,这使得 IconFont 成为 Web 开发时图标的热门选择。

优点

  • 可以方便地将任何 CSS 效果应用于它们。
  • 因为它们是矢量图形,所以它们是可伸缩的。这意味着我们可以在不降低质量的情况下伸缩它们。
  • 我们只需要发送一个或少量 HTTP 请求来加载它们,而不是像图片,可能需要多个 HTTP 请求。
  • 由于尺寸小,它们加载速度快。
  • 它们在所有浏览器中都得到支持(甚至支持到 IE6)。

不足

  • 不能用来显示复杂图像
  • 通常只限于一种颜色,除非应用一些 CSS 技巧
  • 字体图标通常是根据特定的网格设计的,例如 16x16, 32×32, 48×48等。如果由于某种原因将网格系统改为25×25,可能不会得到清晰的结果

25.页面统计数据中,常用的 PV、UV 指标分别是什么?

PV(页面访问量)

即页面浏览量或点击量,用户每1次对网站中的每个网页访问均被记录1个PV。

用户对同一页面的多次访问,访问量累计,用以衡量网站用户访问的网页数量。

UV(独立访客)

是指通过互联网访问、浏览这个网页的自然人。访问您网站的一台电脑客户端为一个访客。

00:00-24:00内相同的客户端只被计算一次。

26.什么是 DOM 和 BOM?

  • DOM 指的是文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理网页内容的方法和接口。
  • BOM 指的是浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的法和接口。BOM的核心是 window,而 window 对象具有双重角色,它既是通过 js 访问浏览器窗口的一个接口,又是一个 Global(全局)对象。这意味着在网页中定义的任何对象,变量和函数,都作为全局对象的一个属性或者方法存在。window 对象含有 location 对象、navigator 对象、screen 对象等子对象,并且 DOM 的最根本的对象 document 对象也是 BOM 的 window 对象的子对象。

27.说说 HTML、XML、XHTML 的区别

  • HTML:超文本标记语言,是语法较为松散的、不严格的Web语言;
  • XML:可扩展的标记语言,主要用于存储数据和结构,可扩展;
  • XHTML:可扩展的超文本标记语言,基于XML,作用与HTML类似,但语法更严格。

28.页面导入样式时,使用link和@import有什么区别?

link属于HTML标签,而@import是css提供的;

页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载;

@import只在IE5以上才能识别,而link是XHTML标签,无兼容问题;

link方式的样式的权重高于@import的权重。

29.简单描述从输入网址到页面显示的过程

简单来说,共有以下几个过程:

  • DNS解析
  • 发起TCP连接
  • 发送HTTP请求
  • 服务器处理请求并返回HTTP报文
  • 浏览器解析渲染页面
  • 连接结束

下面我们来看看具体的细节。

DNS解析

DNS解析实际上就是寻找你所需要的资源的过程。假设你输入www.baidu.com,而这个网址并不是百度的真实地址,互联网中每一台机器都有唯一标识的IP地址,这个才是关键,但是它不好记,乱七八糟一串数字谁记得住啊,所以就需要一个网址和IP地址的转换,也就是DNS解析。

DNS解析其实是一个递归的过程。

输入www.google.com网址后,首先在本地的域名服务器中查找,没找到去根域名服务器查找,没有再去com顶级域名服务器查找,,如此的类推下去,直到找到IP地址,然后把它记录在本地,供下次使用。大致过程就是.-> .com ->google.com. -> www.google.com.。 (最后这个.对应的就是根域名服务器,默认情况下所有的网址的最后一位都是.,为了方便用户,通常都会省略,浏览器在请求DNS的时候会自动加上)

DNS优化

既然已经懂得了解析的具体过程,我们可以看到上述一共经过了N个过程,每个过程有一定的消耗和时间的等待,因此我们得想办法解决一下这个问题!

  • DNS缓存

DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。

  • DNS负载均衡

比如访问baidu.com的时候,每次响应的并非是同一个服务器(IP地址不同),一般大公司都有成百上千台服务器来支撑访问。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡。

发起TCP连接

TCP提供一种可靠的传输,这个过程涉及到三次握手,四次挥手。

三次握手

img

预览

  • 第一次握手:

客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;

  • 第二次握手:

服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  • 第三次握手:

客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

四次挥手

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,假设客户端主动关闭,服务器被动关闭。

img

预览

  • 第一次挥手:

客户端发送一个FIN,用来关闭客户端到服务器的数据传送,也就是客户端告诉服务器:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,客户端依然会重发这些数据),但是,此时客户端还可以接受数据。

FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

  • 第二次挥手:

服务器收到FIN包后,发送一个ACK给对方并且带上自己的序列号seq,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

  • 第三次挥手:

服务器发送一个FIN,用来关闭服务器到客户端的数据传送,也就是告诉客户端,我的数据也发送完了,不会再给你发数据了。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

  • 第四次挥手:

主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

至此,完成四次挥手。

发送HTTP请求

发送HTTP请求,就是构建HTTP请求报文,并通过TCP协议,发送到服务器指定端口。

请求报文由请求行请求报头请求正文组成。

服务器处理请求并返回HTTP报文

对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,比如Tomcat, Nginx和Apache等Web服务器。

HTTP报文也分成三段:状态码响应报头响应报文

浏览器解析渲染页面

img

预览

这个图就是Webkit解析渲染页面的过程。

  • 解析HTML形成DOM树
  • 解析CSS形成CSSOM 树
  • 合并DOM树和CSSOM树形成渲染树
  • 浏览器开始渲染并绘制页面

30.简述 html 页面渲染过程

整个渲染过程其实就是将URL对应的各种资源,通过浏览器渲染引擎的解析,输出可视化的图像。

基本概念

  • HTML解释器:解释HTML语言的解释器,本质是将HTML文本解释成DOM树(文档对象模型)。
  • CSS解释器:解释样式表的解释器,其作用是将DOM中的各个元素对象加上样式信息,从而为计算最后结果的布局提供依据。
  • 布局:将DOM和css样式信息结合起来,计算它们的大小位置等布局信息,形成一个能够表示这所有信息的内部表示模型即渲染树。
  • JavaScript引擎:JavaScript可以修改网页的内容,也能修改CSS的信息,JavaScript引擎解释JavaScript代码并把代码的逻辑和对DOM和CSS的改动信息应用到布局中去,从而改变渲染的结果。

基本过程

  • 1.解析HTML文件,创建DOM树

浏览器解析html源码,然后创建一个 DOM树。并行请求 css/image/js在DOM树中,每一个HTML标签都有一个对应的节点,并且每一个文本也都会有一个对应的文本节点。DOM树的根节点就是 documentElement,对应的是html标签。

  • 2.解析CSS,形成CSS对象模型

浏览器解析CSS代码,计算出最终的样式数据。构建CSSOM树。对CSS代码中非法的语法它会直接忽略掉。解析CSS的时候会按照如下顺序来定义优先级:

浏览器默认设置 < 用户设置 < 外链样式 < 内联样式 < html中的style。

  • 3.将CSS与DOM合并,构建渲染树(renderingtree)

DOM Tree + CSSOM –> 渲染树(rendering tree)。渲染树和DOM树有点像,但是是有区别的。DOM树完全和html标签一一对应,但是渲染树会忽略掉不需要渲染的元素,比如head、display:none的元素等。而且一大段文本中的每一个行在渲染树中都是独立的一个节点。渲染树中的每一个节点都存储有对应的css属性。

  • 4.布局和绘制

一旦渲染树创建好了,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

以上四个步骤并不是一次性顺序完成的。如果DOM或者CSSOM被修改,以上过程会被重复执行。实际上,CSS和JavaScript往往会多次修改DOM或者CSSOM。

Repaint(重绘)

重绘是改变不影响元素在网页中的位置的元素样式时,譬如background-color(背景色), border-color(边框色),visibility(可见性),浏览器会根据元素的新属性重新绘制一次(这就是重绘,或者说重新构造样式),使元素呈现新的外观。

重绘不会带来重新布局,所以并不一定伴随重排。

Reflow(重排)

渲染对象在创建完成并添加到渲染树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。

“重绘"不一定需要"重排”,比如改变某个网页元素的颜色,就只会触发"重绘",不会触发"重排",因为布局没有改变。

但是,“重排"必然导致"重绘”,比如改变一个网页元素的位置,就会同时触发"重排"和"重绘",因为布局改变了。

引申问题:浏览器如何优化渲染?

  • 将多次改变样式属性的操作合并成一次操作
  • 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
  • 由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次重排。

31.HTML5 有哪些新特性?

  • 新增语义化标签:nav、header、footer、aside、section、article
  • 音频、视频标签:audio、video
  • 数据存储:localStorage、sessionStorage
  • canvas(画布)、Geolocation(地理定位)、websocket(通信协议)
  • input标签新增属性:placeholder、autocomplete、autofocus、required
  • history API
    • go、forward、back、pushstate

32.HTML 标签中的 src 和 href 有什么区别

  • href 是超文本引用,它是指向资源的位置,建立与目标文件的联系;
  • src 目的是把资源下载到页面中;

浏览器解析 href 不会阻塞对文档的处理(这就是官方建议使用 link 引入而不是 @ import 的原因),src 会阻塞对文档的处理。

33.script 标签中, async 和 defer 两个属性有什么用途和区别?

在 HTML 中会遇到以下三类 script:

<script src='xxx'></script>
<script src='xxx' async></script>
<script src='xxx' defer></script>

script标签用于加载脚本与执行脚本,直接使用script脚本时,html会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM渲染。

比如现在大家习惯于在页面中引用各种第三方脚本,但如果第三方服务商出现了一些小问题,比如延迟之类的,就会使得页面白屏。

针对上述情况,script标签提供了两种方式来解决问题,就是加入属性async以及defer,这两个属性使得script标签加载都不会阻塞DOM的渲染。

defer:此布尔属性被设置为向浏览器指示脚本在文档被解析后执行。
async:设置此布尔属性,以指示浏览器如果可能的话,应异步执行脚本。

defer

如果script标签设置了defer属性,则浏览器会异步下载该文件并且不会影响后续DOM的渲染。

如果有多个设置了defer属性的script标签存在,则会按照顺序执行所有的script,defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。

async

async属性会使得script脚本异步的加载并在允许的情况下执行,而async的执行并不会按照script标签在页面中的顺序来执行,而是谁先加载完谁先执行。

34.什么是 HTML 语义化?

先看下什么是HTML:

超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。 HTML元素是构建网站的基石。HTML允许嵌入图像与对象,并且可以用于创建交互式表单,它被用来结构化信息——例如标题、段落和列表等等,也可用来在一定程度上描述文档的外观和语义。

那么如何理解 Web 语义化?

通俗的来讲就是从代码上来展示页面的结构,而不是从最终视觉上来展示结构。

单纯的HTML代码是不带任何样式的只是用来标记这一段是标题、这一块是代码、那一个是要强调的内容等等。

但是为什么我们只写HTML在浏览器中不同的标签也是有不同的样式呢?

那是因为各个浏览器都自带的有相应标签的默认样式,为了方便在没有设定样式的情况下友好的展示页面。

良好的语义化代码可以直接从代码上就能看出来那一块到底是要表达什么内容。

为什么要使用语义化标签?

有伙伴会认为,我用DIV+CSS也能做出来一样的效果,虽然单纯看实现效果,两者并没有什么区别。

但是页面不止是给人看的,机器也要看爬虫也要看,网页结构更清晰方便开发维护。

特别是在网络或其他原因页面样式文件丢失的时候,良好语义结构组成的页面,肯定比全是div的页面对用户更友好。

总结下语义化的优点:

  • 标签语义化有助于构架良好的HTML结构,有利于搜索引擎的建立索引、抓取。简单来说。
  • 有利于不同设备的解析(屏幕阅读器,盲人阅读器等)
    的话,应异步执行脚本。

## defer

如果script标签设置了defer属性,则浏览器会异步下载该文件并且不会影响后续DOM的渲染。

如果有多个设置了defer属性的script标签存在,则会按照顺序执行所有的script,defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。

## async

async属性会使得script脚本异步的加载并在允许的情况下执行,而async的执行并不会按照script标签在页面中的顺序来执行,而是谁先加载完谁先执行。

# 34.什么是 HTML 语义化?

先看下什么是HTML:

> 超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。 HTML元素是构建网站的基石。HTML允许嵌入图像与对象,并且可以用于创建交互式表单,它被用来结构化信息——例如标题、段落和列表等等,也可用来在一定程度上描述文档的外观和语义。

那么如何理解 Web 语义化?

通俗的来讲就是从代码上来展示页面的结构,而不是从最终视觉上来展示结构。

单纯的HTML代码是不带任何样式的只是用来标记这一段是标题、这一块是代码、那一个是要强调的内容等等。

但是为什么我们只写HTML在浏览器中不同的标签也是有不同的样式呢?

那是因为各个浏览器都自带的有相应标签的默认样式,为了方便在没有设定样式的情况下友好的展示页面。

良好的语义化代码可以直接从代码上就能看出来那一块到底是要表达什么内容。

## 为什么要使用语义化标签?

有伙伴会认为,我用DIV+CSS也能做出来一样的效果,虽然单纯看实现效果,两者并没有什么区别。

但是页面不止是给人看的,机器也要看爬虫也要看,网页结构更清晰方便开发维护。

特别是在网络或其他原因页面样式文件丢失的时候,良好语义结构组成的页面,肯定比全是div的页面对用户更友好。

总结下语义化的优点:

- 标签语义化有助于构架良好的HTML结构,有利于搜索引擎的建立索引、抓取。简单来说。
- 有利于不同设备的解析(屏幕阅读器,盲人阅读器等)
- 有利于构建清晰的机构,有利于团队的开发、维护

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值