秋招面试准备HTML与CSS - Go语言中文社区

秋招面试准备HTML与CSS


1  HTML5 drag api参考html5 drag api详解 - 城池 - 博客园 (cnblogs.com)

要让一个元素支持拖拽,首先我们需要在标签上标示出来

<div draggable="true"></dv>

元素在拖动过程中可能触发的事件,如下:

1,dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发

2,drag:事件主体是被拖放元素,在正在拖放被拖放元素时触发

3,dragenter:事件主体是目标元素,在被拖放元素放入某元素时触发

4,dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。

5,dropleave:事件主体是目标元素,在被拖放元素移出目标元素时触发。

6,drop:事件出体是目标元素,在目标完全接受被拖放元素时触发

7,dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

其中事件主体是拖放元素的是,dragstart(开始拖动) 、darg(正在拖放) 、dragend(拖放结束),其他4个事件主体都是目标元素,进入、移动、离开、完全进入四个状态。

有了HTML5 drag API,判断拖拽元素跟其他dom元素相交变得容易起来了,只需要:

$('.drop-area').on('dragover',function(e){
    console.log('dragover');
    e.preventDefault();
});
$('.drop-area').on('drop',function(e){
    console.log('drop');
});

需要注意的是,必须写上e.preventDefault(),如果不阻止默认事件,drop事件将不会触发。关于这点,可以去w3c查看。

2  HTTP2.0 参考HTTP2.0 - 简书 (jianshu.com)

HTTP2.0 核心变化:二进制分帧

在应用层(HTTP2.0)和传输层(TCP、UDP)新增二进制分帧层。

在二进制分帧层上,HTTP2.0会将所有传输的信息分割成更小的信息和帧,并进行二进制格式的编码,HTTP1.1的head信息会被封装到Headers帧,request body中的数据会封装到Data帧里面。

PUSH_PROMISE frame(推送帧):这种帧是由server端发送给client的帧,用来表示server push的帧,这种帧是实现server push的主要帧类型。
RST_STREAM(取消推送帧):这种帧表示请求关闭帧,简单讲就是当client不想接受某些资源或者接受timeout时会向发送方发送此帧,和PUSH_PROMISE frame一起使用时表示拒绝或者关闭server push。

然后,HTTP2.0通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。响应地,每个数据流以小消息的形式发送,而信息由一个或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。

头部压缩

HTTP2 .0在客户端和服务端使用首部表来跟踪和存储之间发送的键值对,对于相同的数据,不在通过每次请求和响应发送,通信期间几乎不会改变的键值对(用户代理、可接受的媒体类型,等等)只需要发送一次。事实上,如果请求中不包含首部(例如对统一资源的轮询请求)。那么,首部开销就是零字节。此时,所有首部都自动使用之前请求发送的首部。

如果首部发生变化了,那么只需要发送变化了数据在Headers帧里面,新增或修改的首部帧会被追加到“首部表”,首部表在HTTP2.0的连接存续期内始终存在,由客户端和服务器功能渐进地更新。

所有的HTTP请求在一个连接上

HTTP2.0所有通信都是在一个TCP连接上完成。HTTP2.0把HTTP协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个TCP连接上双向交换信息。就好比,请求一个页面http://www.qq.com。页面上所有的资源请求都是客户端与服务器上的一条TCP上请求和响应的。

HTTP性能的关键在于低延迟而不是高带宽!大多数HTT连接的时间都很短,而且是突发性的,但TCP只在长时间连接传输大块数据时效率才最高。HTTP2.0通过让所有数据流共用一个连接,可以更有效地使用TCP连接,让高带宽也能真正的服务于HTTP性能提升

同时,单链接多资源的方式,使得自上而下的层面都得到了好处:

  1. 可以减少服务链接压力,内存占用少了,连接吞吐量大了
  2. 由于 TCP 连接减少而使网络拥塞状况得以改观;
  3. 慢启动时间减少,拥塞和丢包恢复速度更快

并行双向字节流的请求和响应 

在HTTP2.0上,客户端和服务器可以把HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。注意,同一链接上有多个不同方向的数据流在传输。客户端可以一边乱序发送stream,也可以一边接收者服务器的响应,而服务器那端同理。

把 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2.0 最 重要的一项增强。事实上,这个机制会在整个 Web 技术栈中引发一系列连锁反应, 从而带来巨大的性能提升,因为:

可以并行交错地发送请求,请求之间互不影响;
可以并行交错地发送响应,响应之间互不干扰;
只使用一个连接即可并行发送多个请求和响应;
消除不必要的延迟,从而减少页面加载的时间;

HTTP2.0的请求优先级

每个HTTP2.0流里面有个优先值,这个优先值确定着客户端和服务器处理不同的流采取不同的优先级策略,高优先级的流都应该优先发送,但又不会绝对的。绝对地准守,可能又会引入首队阻塞的问题:高优先级的请求慢导致阻塞其他资源交付。分配处理资源和客户端与服务器间的带宽,不同优先级的混合也是必须的。

HTTP2.0的服务器推送

HTTP 2.0 新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。换句话说,服务器可以强奸你的浏览器,哦不,应该是,除了对最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确地请求。
当浏览器请求一个html,服务器其实大概知道你是接下来要请求资源了,而不需要等待浏览器得到html后解析页面再发送资源请求。我们常用的内嵌图片也可以理解为一种强制的服务器推送:我请求html,却内嵌了张黄图。

有了HTTP2.0的服务器推送,HTTP1.x时代的内嵌资源的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)。当然,你是个正直的浏览器,是可以决绝服务器推送的黄图的
 

3 Web Worker和Web Socket  参考HTML5简明教程(六)Web Socket和Web Worker - 云+社区 - 腾讯云 (tencent.com)

HTML5的web Socket可以让服务器主动向客户端发送消息,非常适合开发聊天室,多人游戏等协作应用。

Web Worker能够让JavaScript真正意义上实现多线程,并擅长处理大数据计算。

1.web Socket

web socket是一种协议,本质和HTTP,tcp一样,它的URL前缀是ws://或者wss://,后者是加密的。为了使用web socket,需要在web服务器上运行特殊程序,负责协调前后台通信。

以前,为了实现客户端和服务端长连接,一般采用 setInterval/setTimeout   轮询,或者xmlHttpRequest长轮询,但是这些方案不算是真正意义上的服务器推送。Web Socket出现之后,让网页和Web服务器保持持久连接,并且,web服务器可以随时让客户端推送信息。

实现的核心就是 WebSocket对象,监听事件的API有:onopen,onmessage,onclose,onerror,触发事件的API有:send,close。下面是一个简单的客户端例子。

var socket; 
$("#connect").click(function(event){ 
  // 初始化WebSocket对象
  socket = new WebSocket("ws://127.0.0.1:8080/getLog"); 
  // 连接建立后触发
  socket.onopen = function(){ 
    console.log("Socket has been opened"); 
  } 
  // 从服务器收到消息后触发
  socket.onmessage = function(msg){ 
    console.log("get log: " + msg.data); 
  } 
  // 连接关闭时触发
  socket.onclose = function() { 
    alert("Socket has been closed"); 
  } 
  // 连接出现问题时触发
  socket.onerror = function() { 
    console.log(“Web Socket Error!”); 
  } 
}); 

$("#send").click(function(event){ 
  // 客户端向服务端发送消息
  socket.send("send from client"); }
); 

$("#close").click(function(event){ 
  // 关闭连接
  socket.close(); 
})

2.web worker

web worker是一个独立的JavaScript线程,运行在后台,适合做费时的大数据计算。

特点有:

1 无法访问window或者document对象

2不能和前台页面共享数据

3不影响前台页面任何操作

4可以创建多个worker线程,每个worker代码要放在一个独立的JS文件中。

HTML5提供worker对象创建新线程,主页面与web worker线程通过postMessage 传递;通过添加onmessage事件监听消息变化,获取接受到的消息。下面是一个简单的例子:

/*------------主线程 index.js---------------*/
var data = {"name": "主线程", index: 1};
var myWorker = new Worker("subworker.js");
// 主线程监听消息事件
myWorker.addEventListener("message", function (oEvent) {
  console.log("工作线程的结果:" + oEvent.data["name"] + oEvent.data["index"]);
}, false);
// 客户端发送消息
myWorker.postMessage(data); 

$("#stop").click(function () {
  // 停止web worker
  myWorker.terminate();
});

/*------------子线程 subworker.js---------------*/
// 子线程监听消息事件
onmessage = function (oEvent) {
  var data = oEvent.data;
  data["name"] = "我是子线程";
  // 子线程向主线程发送消息
  postMessage(data);
};

4 H5的语义化作用及语义化标签什么是HTML语义化标签?为什么要用H5语义化标签?HTML5语义化标签有哪些_panda_2022的博客-CSDN博客

什么是HTML语义化标签?

语义化标签,就是让标签有自己的含义,利用本身传达它所包含内容的一些信息,使浏览器和搜索引擎直观的认识标签和属性的用途和作用。

过去我们常常采用DIV+CSS的方式布局页面,但DIV标签本身没有独特的含义,这样做的结果就是文档结构不够清晰,不利于浏览器对页面的读取,在分离CSS样式后,用户体验不友好。

所以HTML5新增了很多语义化标签,使文档更具可读性,页面结构更清晰。

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

1,代码结构清晰,可读性高,减少差异化,便于团队开发和维护。

2,在页面没有加载CSS的情况下,也能呈现良好的内容结构,增加用户体验。

3,对搜索引擎友好,良好的结构和语义,有助于爬虫抓取更多的有效信息。

HTML5语义化标签有哪些?

header标签:页眉,通常包括网站标志、主导航、全站链接以及搜索框

nav标签:标记导航,仅对文档中重要的链接群使用

main标签:页面主要内容,一个页面只能使用一次

article标签,用来定义独立于文档且有意义的来自外部的内容

section标签:定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。

aside标签:定义article标签外的内容,可用作文章的侧边栏

footer标签:页脚,只有当父级是body时,才是整个页面的页脚

title标签,定义文档的标题

h1-h6标签:创建文档结构的层级关系

ul标签:无序列表

ol标签:有序列表

strong标签,强调文本,表现为粗体

em标签,强调文本,表现为斜体

p标签,段落

5 iframe是什么?有什么缺点? 参考iframe是什么?有什么缺点?__牛客网 (nowcoder.com)

首先说一下iframe有什么作用:

iframe元素会创建一个包含另一个文档的内联框架。提示:可以将提示文字放在<iframe></iframe>之间,来提示那些不支持iframe的浏览器

有点:

1iframe能够原封不动的把嵌入的页面展现出来。

2如果有多个网页引用iframe,那么你只需要修改frame的内容,就可以实现所有调用该iframe的页面内容的更改,方便快捷,网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的复用性。

3如果遇到加载缓慢的第三方内用如图表和广告,这些问题都可以由iframe来解决

缺点:

1 iframe会阻塞主页的onload事件

2 iframe和主页面共享连接池,而浏览器对相同与的连接有限制,所以会影响页面的并行和加载

3 会产生很多页面,不容易管理。

4 iframe框架结构有时会让人感到迷惑,如果框架个数多的话,可能 会出现上下、左右滚动条,会分散访问者的注意力,用户体验差。

5 代码复杂,无法被一些搜索引擎搜索到,这一点很关键,现在的搜索引擎爬虫还不能很好的处理iframe的内容,所以使用iframe会不利于搜索引擎优化(SEO)

6 很多的移动设备无法显示框架,设备兼容性差

7 iframe框架页面会增加服务器的http请求,对于大型网站是不可取的

8 安全性也是一个大问题,过去我们访问一个网站,可能会忽然唰唰唰跳过了好几个网站,最后跳到了一个不知道又是啥的广告网站,这就表示我们的iframe被iframe了。

现在基本上都是用Ajax来代替iframe,所以iframe已经渐渐的退出了前端开发。

如果需要使用iframe,最好是通过javascript动态给iframe添加src属性值,这样可以绕开以上一些问题。

6 Doctype作用?严格模式与混杂模式如何区分?它们有何意义  参考Doctype作用? 严格模式与混杂模式如何区分?它们有何意义?_前端校招面试题目合集_牛客网 (nowcoder.com)

1声明位于文档中的最前面,处于标签之前,告诉浏览器的解析器,用什么文档类型规范来解析这个文档。

2 严格模式的排版和JS运行模式是以该浏览器支持的最高标准运行。

3 在混杂模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。、

4 DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。

7 如何画一个三角形如何在HTML里画一个三角形_DadaChao的博客-CSDN博客_html画三角形

三角形原理:边框的均分原理

首先:要是我们画一个正方形,然后把正方形的边框设置粗一些

代码如下:

		        width: 20px;    
				height: 20px;  
				border: 40px solid ;   
				border-color: red yellow green blue; 

效果图如下:

这样就得到了四个等腰梯形

要是我们把正方形设置成高度0px宽度0px

代码如下

		        width: 0px;    
				height: 0px;  
				border: 40px solid ;   
				border-color: red yellow green blue; 

效果图如下:

所以我们就得到了一个由四个三角形组成的正方形。

然后我们可以将四个三角形根据需要设置成透明色,即可获得所需要的的三角形

例如,获取一个尖朝上的三角形

 

 我们只需要将上、左、右三边的颜色设置成透明色

border-color: transparent transparent green transparent;

其他的不需要改变,这样,就可以随意获得四个角度的三角形了。

8HTML5新增元素HTML5新增元素的介绍_Assassin大神的博客-CSDN博客_html5新增元素

一:html5新增的主体元素

<article>:定义页面独立的内容区域(可以嵌套使用,可以表示插件)。

<section>:定义文档中的节(section,区段)。

<nav>定义导航链接的部分

<aside>定义页面的侧边栏内容

<time>定义日期或时间

二:HTML5新增的非主体元素

<header>定义了文档的头部区域

<footer>定义section或document的页脚

<hgroup>被用来对标题元素进行分组

<adderess>:定义文档作者/所有者的联系信息

三:form表单新增元素与属性

html<input>formaction:formaction属性规定当表单提交时处理输入控件的文件的URL

html<input>formmethod:formmethod属性定义发送表单数据到action URL的HTTP方法

html<input>formenctype:formenctype 属性规定当表单数据提交到服务器时如何编码,仅适用于 method="post" 的表单

html <input>formtarget:formtarget 属性规定表示提交表单后在哪里显示接收到响应的名称或关键词。(_blank新窗口响应)

html <input>autofocus:autofocus 属性规定当页面加载时 <input> 元素应该自动获得焦点。(布尔值)

html <input>required:required 属性规定必需在提交表单之前填写输入字段。(布尔值)

html <input>labels属性:                      html <input>control属性:设置默认值

html <input>placeholder:placeholder属性当文本框处于未输入状态时显示输入提示。

html <input>list:list属性的值为某个datalist元素的id,类似下拉选择框,但是允许自行输入。

html <input>autocomlistplete:cutocomlistplete属性帮助输入所用的自动完成功能,是一个既节省输入时间又十分方便的功能。

html <input>pattern:pattern 属性规定用于验证 <input> 元素的值的正则表达式。

html <input>selectiondirection:当用户在这两个元素中用鼠标选取部分文字时,可以使用该属性获取选取方向。

html <input>indeterminate:可以在javascript脚本代码中说明复选框处于“尚未明确是否选取”状态。(选取、非选取,不明确)

img提交按钮的height和width:用来指定图片按钮的高度和宽度。
四:html5改良的input元素

type="url"(一个网址,带自验证)type="email"(一个邮箱,带自验证)type="date"(日期,可以自己选取)

type="time"(输入时间的文本框,带自验证)type="datetime"(专门输入utc时间的文本框)

type="datetimelocal"(专门在本地输入时间的文本框)type="mouth"(专门输入月份的文本框)

type="week"(专门输入周号的文本框)type="unmber"(转本输入数字的文本框)type="search"(搜索关键字的文本框)

type="tel"(用来输入电话号码的文本框)type="color"(选取颜色,提供一个颜色选取器)

<output>:定义不同类型的输入。

六:html5增强的页面元素

<figure>:用来表示网页上独立的内容(可以是图片、统计表格、音视频插件.....)

<figcaption>:从属于figure元素,表示figure元素的标题

<details>:用来表示该元素内部的子元素,可以别展开或者收缩的元素(布尔类型)

<summary>:从属于details元素

<mark>:突出显示或者高量显示的对当前用户有参考作用的一段文字

<ol>:[ol---li,,,,,start="5"(列表从5开始),,,reversed(倒序效果)]

<dl>:[dl---dt----dd,,,表示多个名字的列表]

<cite>:表示作品的标题

<small>:表示标识小字印刷体的元素

<porgress>:代表任务的完成进度(进度条)

<meter>:规定范围内的数值量(进度条)

七:html5编辑API之range对象

一个range对象代表页面上的一段连续区域,通过range对象,可以获取或修改网页上的任何区域。

主要的对象属性有:selection,selectNode,selecNodeContents,deleteContents,setstart,setstarBefore.........

总结:首先html5为了更好的实践web语义化,增加了header,footer,nav,aside,section等语义化标签,在表单方面,为了增强表单,为input增加了color,emial,data ,range等类型,在存储方面,提供了sessionStorage,localStorage,和离线存储,通过这些存储方式方便数据在客户端的存储和获取,在多媒体方面规定了音频和视频元素audio和vedio,另外还有地理定位,canvas画布,拖放,多线程编程的web worker和websocket协议

9HTML5和CSS3的新特性

1HTML5的新特性(记住有九大模块内容)

添加了video、radio标签

添加了canvas画布和SVG渲染矢量图片

添加了一些语义化标签header,footer,mian,section,aside,nav等

input的type值新添加了很多属性(email,url,number,range,Date pickers(date,month,week,time,datetime,datetime-local),search,color)

添加了地理位置定位功能 Geolocation API

添加了web存储功能,localStorage 和sessionStorage

使用HTML5,通过创建cache mainifest文件,可以轻松创建web应用的离线版本

web worker是运行在后台的JavaScript,独立于其他脚本,不会影响页面的性能,可以继续做任何原意做的事情:点击、选取内容等等,而此时的web worker在后台运行。

服务端事件推送(EventSource对象用于接收服务器发送事件通知),所有主流浏览器均支持服务器发送事件,除了Internet Explorer

2CSS3中心添加的特性

媒体查询(可以查询设备的物理像素然后进行自适应操作)

transform,transition,translate,scale,skelw,rotate等相关动画效果

box-shadow,text-shadow等特效

CSS3 @font-face规则,设计师可以引入任意的字体了

CSS3 @keyframes规则,可以自己创建一些动画等

2D,3D转换

添加了border-radius,border-image等属性

CSS3创建多列(column-count规定文本可以以几列的方式布局)

CSS3用户界面(resize,box-sizing,outline-offset)

div{
    resize:both; /*规定元素的尺寸可以由用户进行手动的调整*/
    overflow:auto;
}
div{
    box-sizing:border-box;
    -moz-box-sizing:border-box;	     /* Firefox */
    -webkit-box-sizing:border-box;	/* Safari */
    width:50%;
    float:left;
}
div{
    margin:20px;
    width:150px; 
    padding:10px;
    height:70px;
    border:2px solid black;
    outline:2px solid red;  /*在元素的外围添加一层轮廓,轮廓是不占位置的*/
    outline-offset:12px;    /*轮廓距离border的距离*/
}

10 WEB性能优化web 性能优化 - 鸡腿太小 - 博客园 (cnblogs.com)

三个部分

js部分

一、减少http请求

web中一次请求要经历发起请求,服务器响应,返回数据,浏览器渲染才能把数据展示在页面上,其中80%的时间都耗在http请求中,只有20%是浏览器渲染时间

二、减少对dom的访问和操作,改为创建文档碎片,进行虚拟dom操作

在浏览器中访问dom节点需要调用查找方法,每个找都是要进行遍历循环才能找到,特别是对于嵌套比较深的dom节点进行查找,过程非常缓慢,与此同时,对dom进行增删改查的操作耗费浏览器的性能更大,这也是vue比较火,jq越来越少有人用的原因。

三、dns缓存,浏览器缓存(localstorage、sessionstorage)

dns缓存是当正常访问ip后系统会将这个ip存储起来,当再次访问的时候,系统就直接把本地的DNS缓存提取显示,等于是加速了网址的解析;浏览器缓存包括页面html缓存和图片,js,css等资源的缓存到用户本地电脑硬盘里,是服务器响应更快和减少网络带宽消耗

四、使用异步加载外部js资源和外部资源本地化

对于一些外部资源使用非阻塞异步加载的办法,不阻塞页面加载,比较大的资源下载到本地加载,提高资源加载稳定性

HTML部分

一、标签语义化

即用合理、正确的标签来展示内容,比如h1-h6定义标题,使其易于用户阅读,样式丢失的时候能让页面呈现清晰的结构

二、合理规划页面结构:

使用合理的页面结构,使代码更加清晰,有利于后期的维护,图片较小和不重要的转为base64格式,提升加载速度,尽量减少DOM元素的数量与层级

三、选择器的合理使用

根据项目大小,选择器主要使用class和id,id选择器优先级更高,访问速度最快。但是在html中每声明一个id,就会在JS底层声明一个全局变量,而全局变量的增多,将会拖慢JS中变量遍历的效率,若变量遍历达到十万次以上,就会出现显著的延迟,而且容易造成全局变量污染,对于小项目,并无影响,但对中大型项目来说,尤其是游戏项目,影响很大,个人推荐,当项目较小时,灵活使用class和id,当项目较大时,尽量少使用id

四、使用异步加载iframe标签和尽量避免使用table标签

浏览器加载iframe标签时,会阻塞父页面渲染树的构建及HTTP请求,因此尽量使用异步加载iframe;浏览器对table标签的解析是全部生成后再一次性绘制的,因此会造成表格位置长时间的空白,推荐使用ul以及li标签绘制表格。

CSS样式:

一、禁止使用样式表达式

css表达式从IE5起开始支持,但仅有IE支持。它的解析速度很慢,而且运算次数远比我们想象的要大,随意动动鼠标就能轻松达到上万次运算,会对页面性能造成影响。

二、优化关键选择器:

去掉无效的父级选择器,尽量少在选择器末尾使用通配符,浏览器对CSS选择器的解析式从右往左进行的,减少中间的无效的父级选择器,大大提高效率

三、将CSS放在HTML的上面部分

这个策略不能提高网站的加载速度,但它不会让访问者看着空白屏幕或者无格式的文本(FOUT)等待。如果网页大部分可见元素已经加载出来了,访问者才更有可能等待加载整个页面,从而带来对前端的优化效果,这就是知觉性能。

四、使用CSS雪碧图

将多个图片合并成一个图片(即将多个HTTP请求减少为一个HTTP请求),然后以位置信息定位超链接

五、使用link而不是@import

加载页面时,link标签引入的CSS被同时加载;@import引入的CSS将在页面加载完毕后被加载,也就是说,@import会组织浏览器并行下载;link是HTML的元素,不存在兼容问题;@import只有IE5+才能识别

六、减少重排和减少重绘

七、合并、压缩CSS文件

11 盒模型面试汇总——说一下CSS盒模型 - 习惯沉淀 - 博客园 (cnblogs.com)

一、基本概念

盒模型的组成,从里到外依次是content,padding,border,margin

盒模型有两种标准,一个是标准模型,一个是IE模型

标准模型如下图

 所以盒子总宽度为:width+border+padding

IE盒模型如下图

所以盒子总宽度为:width 

二. CSS如何设置这两种模型

这里用到了CSS的属性box-sizing

/* 标准模型 */
box-sizing:content-box;

 /*IE模型*/
box-sizing:border-box;

三. JS如何获取盒模型对应的宽和高

为了方便书写,以下用dom来表示获取的HTML的节点。

1. dom.style.width/height

  这种方式只能取到dom元素内联样式所设置的宽高,也就是说如果该节点的样式是在style标签中或外联的CSS文件中设置的话,通过这种方法是获取不到dom的宽高的。

2. dom.currentStyle.width/height

  这种方式获取的是在页面渲染完成后的结果,就是说不管是哪种方式设置的样式,都能获取到。

  但这种方式只有IE浏览器支持。

3. window.getComputedStyle(dom).width/height

  这种方式的原理和2是一样的,这个可以兼容更多的浏览器,通用性好一些。

 4. dom.getBoundingClientRect().width/height

  这种方式是根据元素在视窗中的绝对位置来获取宽高的。

5.dom.offsetWidth/offsetHeight

  这个就没什么好说的了,最常用的,也是兼容最好的。

边距重叠

什么是边距重叠

如下图,父元素没有设置margin-top,而子元素设置了margin-top:20px;可以看出,父元素也一起有了边距

上面的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .demo{
            height:100px;
            background: #eee;
        }
        .parent{
            height:200px;
            background: #88f;
        }
        .child{
            height:100px;
            margin-top:20px;
            background: #0ff;
            width:200px;
        }
    </style>
</head>
<body>
    <section class="demo">
        <h2>此部分是能更容易看出让下面的块的margin-top。</h2>
    </section>
    <section class = "parent">
        <article class="child">
            <h2>子元素</h2>
            margin-top:20px;
        </article>
        <h2>父元素</h2>
            没有设置margin-top
    </section>
</body>
</html>

边距重叠解决方案(BFC)

首先要明确BFC是什么意思,其全英文拼写为Block Formatting Context只译为“块级格式化上下文”

BFC的原理

1.内部的box会在垂直方向,一个接一个的放置

2.每个元素的margin  box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)

3.box垂直方向的距离由margin决定,属于同一个bfc的两个相邻box的margin会发生重叠

4.bfc的区域不会与浮动区域的box重叠

5.bfc是一个页面上的独立的容器,外面的元素不会影响bfc里的元素,反过来,里面的也不会影响外面的

6.计算bfc高度的时候,浮动元素也会参与计算

怎么去创建bfc

1.float属性不为none(脱离文档流)

2.position为absolute或fixed

3.display为inline-block,table-cell,table-caption,flex,inine-flex

4overflow不为visible

5根元素

应用场景

  1. 自适应两栏布局
  2. 清除内部浮动 
  3. 防止垂直margin重叠

一个垂直margin重叠例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .top{
            background: #0ff;
            height:100px;
            margin-bottom:30px;
        }
        .bottom{
            height:100px;
            margin-top:50px;
            background: #ddd;
        }
    </style>
</head>
<body>

    <section class="top">
        <h1>上</h1>
        margin-bottom:30px;
    </section>
    <section class="bottom">
        <h1>下</h1>
        margin-top:50px;
    </section>

</body>
</html>

 效果图

 用bfc可以解决垂直margin重叠的问题

关键代码

    <section class="top">
        <h1>上</h1>
        margin-bottom:30px;
    </section>

    <!-- 给下面这个块添加一个父元素,在父元素上创建bfc -->
    <div style="overflow:hidden">
        <section class="bottom">
            <h1>下</h1>
            margin-top:50px;
        </section>
    </div>

效果图 

12 画一条0.5px的线画一条0.5px的线 - 简书 (jianshu.com)

像素是屏幕显示最小的单位,在一个1080p的屏幕上,它的像素数量是1920 * 1080,即横边有1920个像素,而竖边为1080个。
像素本身有大小,如果一个像素越小,那么在同样大小的屏幕上,需要的像素点就越多,像素就越密集,如果一英寸有435个像素,那么它的dpi/ppi就达到了435。Macbook Pro 15寸的分辨率为2880 x 1800,15寸是指屏幕的对角线为15寸(具体为15.4),根据长宽比换算一下得到横边为13寸,所以ppi为2880 / 13 = 220 ppi. 像素越密集即ppi(pixel per inch)越高,那么屏幕看起来就越细腻越高清。
在Mac/Windows上可以设置屏幕显示的分辨率,Mac默认为设备分辨率的一半,它的dpr = 2,即长和宽用2个像素表示1个像素,所以2880个物理像素点实际上只表示1440个逻辑像素。那么我们的问题来了,怎么在高清屏上画一条0.5px的边呢?0.5px相当于高清屏物理像素的1px。这样的目的是在高清屏上看起来会更细一点,效果会更好一点,例如更细的分隔线。

直接设置0.5px

如果我们直接设置0.5px,在不同的浏览器会有不同的表现,使用如下代码:

<!DOCType html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        .hr {
            width: 300px;
            background-color: #000;
        }
        .hr.half-px {
            height: 0.5px;
        }
        .hr.one-px {
           height: 1px;
        }
    </style>
</head>
<body>
    <p>0.5px</p>
    <div class="hr half-px"></div>
    <p>1px</p>
    <div class="hr one-px"></div>
</body>
</html>

其中Chrome把0.5px四舍五入变成了1px,而firefox/safari能够画出半个像素的边,并且Chrome会把小于0.5px的当成0,而Firefox会把不小于0.55px当成1px,Safari是把不小于0.75px当成1px,进一步在手机上观察IOS的Chrome会画出0.5px的边,而安卓(5.0)原生浏览器是不行的。所以直接设置0.5px不同浏览器的差异比较大,并且我们看到不同系统的不同浏览器对小数点的px有不同的处理。所以如果我们把单位设置成小数的px包括宽高等,其实不太可靠,因为不同浏览器表现不一样。

使用scale缩放

<style>
.hr.scale-half {
    height: 1px;
    transform: scaleY(0.5);
}
</style>
    <p>1px + scaleY(0.5)</p>
    <div class="hr scale-half"></div>

我们发现Chrome/Safari都变虚了,只有Firefox比较完美看起来是实的而且还很细,效果和直接设置0.5px一样。所以通过transform: scale会导致Chrome变虚了,而粗细几乎没有变化。但是如果加上transform-origin: 50% 100%:

.hr.scale-half {
    height: 1px;
    transform: scaleY(0.5);
    transform-origin: 50% 100%;
}

chrome现在的效果如下

线性渐变linear-gradient

<style>
.hr.gradient {
    height: 1px;
    background: linear-gradient(0deg, #fff, #000);
}
</style>
<p>linear-gradient(0deg, #fff, #000)</p>
<div class="hr gradient"></div>

inear-gradient(0deg, #fff, #000)的意思是:渐变的角度从下往上,从白色#fff渐变到黑色#000,而且是线性的,在高清屏上,1px的逻辑像素代表的物理(设备)像素有2px,由于是线性渐变,所以第1个px只能是#fff,而剩下的那个像素只能是#000,这样就达到了画一半的目的。

boxshadow

<style>
.hr.boxshadow {
    height: 1px;
    background: none;
    box-shadow: 0 0.5px 0 #000;
}
</style>
<p>box-shadow: 0 0.5px 0 #000</p>
<div class="hr boxshadow"></div>

viewport

<meta name="viewport" content="width=device-width,initial-sacle=0.5">

其中width=device-width表示将viewport视窗的宽度调整为设备的宽度,这个宽度通常是指物理上宽度。默认的缩放比例为1时,如iphone 6竖屏的宽度为750px,它的dpr=2,用2px表示1px,这样设置之后viewport的宽度就变成375px。但是我们可以改成0.5,viewport的宽度就是原本的750px,所以1个px还是1px,正常画就行,但这样也意味着UI需要按2倍图的出,整体面面的单位都会放大一倍。

13 css link与import的区别是什么css link与import的区别是什么-css教程-PHP中文网

区别:link属于html标签,而@import是css提供的一种方式,link标签不仅可以引入css,还可以做其他事,而@import只能引入css;@import只有在IE5以上才支持;而link标签不存在兼容性问题。

1、从属关系区别

@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。

2、加载顺序区别

加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。

3、兼容性区别

@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。

4、DOM可控性区别

可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import的方式插入样式。

总体来说:link优于@import,强烈建议使用link标签,慎用@import方式。

14transition和animation的区别css3 transition和animation的区别与联系 - 叶子玉 - 博客园 (cnblogs.com)

1transition

一定时间之内,一组css属性变换到另一组属性的动画展示过程

属性:

transition-property:动画展示哪些属性,可以使用all关键字;

transition-duration:动画过程有多久

transition-timing-function:liner,ease,ease-in,ease-out,ease-in-out,贝塞尔曲线等:控制动画速度变化

transition-delay:动画是否延迟执行

一般来说,将transition属性应用到最初的样式里,而不是放在结束的样式里,即定义动画开始之前的元素外观的样式。只需要给元素设置一次transition,浏览器就会负责以动画展示从一个样式到另一个样式,再返回最初样式的变化过程。

1.需要一个事件来触发,比如hover,所以没法在网页加载时自动触发

2是一次性的,不能重复发生,除非一再触发

3只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态

4一条transition规则,只能定义一个属性的变化,不能涉及多个属性

为了突破这些限制,animation出现了。

2.animation

与transition不同的是,animation可以通过keyframes显示控制当前帧的属性值

而transition只能隐式来进行,不能指定没帧的属性值,所以相对而言animation的功能更加灵活

属性:

animation-name:keyframes中定义的动画名称;

animation-duration:动画执行一次持续的时长

animation-timing-function:动画速率变化的函数

animation-delay:动画延迟执行的时间

animation-iteration-count:动画执行的次数,可以是数字,或者关键字(infinate);

animation-direction:alternate(奇数次超前运行,偶数次后退运行)。

animation-fill-mode:告诉浏览器将元素的格式保持为动画结束时候的样子

比较

1、transition需要去触发比如:点击事件、鼠标移入事件;而animation可以配合@keyframe可以不触发事件就触发这个动画

2、transition触发一次播放一次;而animation则是可以设置很多的属性,比如循环次数,动画结束的状态等等;

3、transition关注的是样式属性的变化,属性值和时间的关系是一个三次贝塞尔曲线;而animation作用于元素本身而不是样式属性,可以使用关键帧的概念,可以实现更自由的动画效果

4、在性能方面:浏览器有一个主线程和排版线程;主线程一般是对js运行的、页面布局、生成位图等等,然后把生成好的位图传递给排版线程,而排版线程会通过GPU将位图绘制到页面上,也会向主线程请求位图等等;我们在使用animation的时候这样就可以改变很多属性,像我们改变了width、height、position等等这些改变文档流的属性的时候就会引起页面的回流和重绘,对性能影响就比较大,但是我们用transition的时候一般会结合transform来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了。

transition

<div class="box"></div>

.box {
      width: 200px;
      height: 200px;
      margin: 50px auto;
      background-color: #00b3f1;
      /* transition: 哪个属性动 运动在多长时间完成 延迟时间 运动类型;*/
      transition: all .5s linear;
 }

.box:hover {
      width: 300px;
      height: 300px;
}

animation

<div class="box"></div>

.box {
    width: 200px;
    height: 200px;
    margin: 50px auto;
    background-color: #00b3f1;
        
    animation-duration: 1s;                 /* 动画时间 */
    animation-name: fillout;                /* 通过name使用 */
    animation-iteration-count: infinite;    /* 循环次数,infinite(无限次循环) */
  }

@keyframes fillout {
    from {
        width: 200px;
        height: 200px;
    }
    to {
        width: 400px;
        height: 400px;
    }
 }

15flex布局30 分钟学会 Flex 布局 - 知乎 (zhihu.com)

Flex基本概念:

preview

在flex容器中默认存在两条轴,水平主轴(main axis)和垂直的交叉轴(cross axis),这是默认的设置,当然你可以通过修改垂直方向变为主轴,水平方向变为交叉轴。

在容器中的每个单元块被称之为flex item,每个项目占据的主轴空间为(main size),占据的交叉轴空间为(cross size)。

需要注意的是,不能先入为主地认为宽度就是main size,高度就是cross size,这个取决于你主轴的方向,如果垂直方向是主轴,那么项目的高度就是main size。

Flex容器

首先,实现flex布局需要先指定一个容器,任何一个容器都可以被指定为flex布局,这样容器内部的元素就可以使用flex来进行布局。

.container {
    display: flex | inline-flex;       //可以有两种取值
}

 分别生成一个块状或行内的flex容器盒子。简单说来,如果你使用块元素如div,就可以使用flex,如果使用行内元素,可以使用inline-flex。

需要注意的是,当时设置flex布局之后,子元素的float,clear,vertical-align的属性将会失效。

有下面六种属性可以设置在容器上:

1、flex-direction

2、flex-wrap

3、flex-flow

4、justify-content

5、align-items

6、align-content

1、flex-direction:决定主轴的方向,即项目的排列方向

.container {
    flex-direction: row | row-reverse | column | column-reverse;
}

默认值:row,主轴为水平方向,起点在左端

 row-reverse:主轴为水平方向,起点在右端

column:主轴为垂直方向,起点在上沿

column-reverse:主轴为垂直方向,起点在下沿

2flex-wrap:决定容器内项目是否可以换行

默认情况下,项目都是排在主轴线上,使用flex-wrap可实现项目的换行。 

.container {
    flex-wrap: nowrap | wrap | wrap-reverse;
}

默认值:nowrap不换行,即当主轴尺寸固定时,当空间不足时,项目尺寸会随之调整而并不会挤到下一行 

wrap:项目主轴总尺寸超出容器时换行,第一行在上方

wrap-reverse:换行,第一行在下方

3. flex-flow: flex-direction 和 flex-wrap 的简写形式

.container {
    flex-flow: <flex-direction> || <flex-wrap>;
}

默认值为: row nowrap,感觉没什么卵用,老老实实分开写就好了。这样就不用记住这个属性了。

4、justify-content:定义了项目在主轴的对齐方式

.container {
    justify-content: flex-start | flex-end | center | space-between | space-around;
}

建立在主轴为水平方向时测试,即flex-direction:row

默认值:flex-start 左对齐

flex-end:右对齐

center:居中

space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙

space-around:每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍

5、align-items:定义了项目在交叉轴上的对齐方式

.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}

建立在主轴为水平方向时测试,即flex-direction:row

默认值为stretch即如果项目未设置高度或者设置为auto,将占满整个容器的高度

假设容器高度设置为100px,而项目都没有设置高度的情况下,则项目的高度也为100px

flex-start:交叉轴的起点对齐 

假设容器高度设置为100px,而项目分别为20px,40px,60px,80px,100px,则如上图显示

flex-end:交叉轴的终点对齐

center:交叉轴的中点对齐

baseline:项目的第一行文字的基线对齐

以文字的底部为主 

6、align-content定义了多跟轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用

.container {
    align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

当flex-wrap设置为nowrap的时候,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线。

当flex-wrap设置为wrap的时候,容器可能会出现多条轴线,这时候需要去设置多条轴线之间的对齐方式

建立在主轴方向时的测试,即,flex-direction:row,flex-wrap:wrap

默认值为stretch

从图可以看出有三条轴线,因为容器宽度有限,当值为stretch时三条轴线平分容器的垂直方向上的空间

注意,虽然每条轴线上项目的默认值也为stretch,但是由于每个项目设置了高度,所以它并没有撑开整个容器,如果项目不设置高度的话就会变成下面这样: 

前面有提到(align-items),这里重点是理解三条轴线会平分垂直轴上的空间

flex-start:轴线全部在交叉轴上的起点对齐 

flex-end:轴线全部在交叉轴上的终点对齐 

center:轴线全部在交叉轴上的中间对齐 

 space-between:轴线两端对齐,之间的间隔相等,即生育空间等分成间隙

space-around:每个轴线两侧的间隔相等,所以轴线之间的间隔比轴线与边缘的间隔大一倍

下面是flex item上的属性。

有六种属性可运用在item项目上:

1、order

2、flex-basis

3、flex-grow

4、flex-shrink

5、flex

6、align-self

1、order:定义项目在容器中的排列顺序,数值越小,排列越靠前,默认值为0

.item {
    order: <integer>;
}

在HTML结果中,虽然-2,-1的item排在后面,但是由于分别设置了order,使之能够排到最前面

2、flex-basis:定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间

.item {
    flex-basis: <length> | auto;
}

 默认值:auto,即本项目本来的大小,这时候item的宽高度取决于width或height的值

当主轴为水平方向的时候,当设置了flex-basis,项目的宽度设置值会失效,flex-basis需要跟flex-grow和flex-shrink配合使用才能发挥效果

当flex-basis值为0%时,是吧该项目视为零尺寸的,故即使声明该尺寸为140px,也并没有什么用

当flex-basis值为auto时,则根据尺寸的设定值(假如为100px),则这100px不会纳入剩余空间

3、flex-grow:定义项目的放大比例 

.item {
    flex-grow: <number>;
}

默认值为0,即如果存在生育空间,也不放大

当所有的项目都以flex-basis的值进行排列后,仍有剩余空间,那么这时候flex-grow就会发挥作用了

如果所有项目的flex-grow属性都为1,则他们将等分剩余空间,如果有的话

如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍

当然如果当所有项目以flex-basis的值排列完后发现空间不够了,且flex-wrap:nowrap时,此时flex-grow则不起作用了,这时候需要接下来的这个属性。

4、flex-shrink定义了项目的缩小比例 

.item {
    flex-shrink: <number>;
}

默认值:1,即如果空间不足,该项目将缩小,负值对属性无效

这里可以看出,虽然每个项目都设置了宽度为50px,但是由于自身容器宽度只有200px,这时候每个项目会被同比例进行缩小,因为默认值为1

同理可得:

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小

如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小

5、flex:flex-grow,flex-shrink和flex-basis的简写 

.item{
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
} 

flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto。

有关快捷值:auto (1 1 auto) 和 none (0 0 auto)

关于 flex 取值,还有许多特殊的情况,可以按以下来进行划分:

  • 当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:
.item {flex: 1;}
.item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 当 flex 取值为 0 时,对应的三个值分别为 0 1 0%
.item {flex: 0;}
.item {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 0%;
}
  • 当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字)

.item-1 {flex: 0%;}
.item-1 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}

.item-2 {flex: 24px;}
.item-2 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 24px;
}
  • 当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%,如下是等同的:

.item {flex: 2 3;}
.item {
    flex-grow: 2;
    flex-shrink: 3;
    flex-basis: 0%;
}
  • 当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1,如下是等同的:
.item {flex: 11 32px;}
.item {
    flex-grow: 11;
    flex-shrink: 1;
    flex-basis: 32px;
}

建议优先使用这个属性,而不是单独写三个分离的属性。

grow 和 shrink 是一对双胞胎,grow 表示伸张因子,shrink 表示是收缩因子。

grow 在 flex 容器下的子元素的宽度和比容器和小的时候起作用。 grow 定义了子元素的尺寸增长因子,容器中除去子元素之和剩下的尺寸会按照各个子元素的 grow 值进行平分加大各个子元素上。

 补充说明容器的 flex-wrap 与子项的 flex-shrink、flex-grow 之间的关系:

  1. 当 flex-wrap 为 wrap | wrap-reverse,且子项宽度和不及父容器宽度时,flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大)
  2. 当 flex-wrap 为 wrap | wrap-reverse,且子项宽度和超过父容器宽度时,首先一定会换行,换行后,每一行的右端都可能会有剩余空间(最后一行包含的子项可能比前几行少,所以剩余空间可能会更大),这时 flex-grow 会起作用,若当前行所有子项的 flex-grow 都为0,则剩余空间保留,若当前行存在一个子项的 flex-grow 不为0,则剩余空间会被 flex-grow 不为0的子项占据
  3. 当 flex-wrap 为 nowrap,且子项宽度和不及父容器宽度时,flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大)
  4. 当 flex-wrap 为 nowrap,且子项宽度和超过父容器宽度时,flex-shrink 会起作用,子项会根据 flex-shrink 设定的值进行缩小(为0的项不缩小)。但这里有一个较为特殊情况,就是当这一行所有子项 flex-shrink 都为0时,也就是说所有的子项都不能缩小,就会出现讨厌的横向滚动条
  5. 总结上面四点,可以看出不管在什么情况下,在同一时间,flex-shrink 和 flex-grow 只有一个能起作用,这其中的道理细想起来也很浅显:空间足够时,flex-grow 就有发挥的余地,而空间不足时,flex-shrink 就能起作用。当然,flex-wrap 的值为 wrap | wrap-reverse 时,表明可以换行,既然可以换行,一般情况下空间就总是足够的,flex-shrink 当然就不会起作用

6、align-self:允许单个项目有与其他项目不一样的对齐方式

单个项目覆盖align-items定义的属性

默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

.item {
     align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

这个跟 align-items 属性时一样的,只不过 align-self 是对单个项目生效的,而 align-items 则是对容器下的所有项目生效的。

Flex 布局教程:语法篇 - 阮一峰的网络日志 (ruanyifeng.com)

16 BFC(块级格式化上下文,用于清楚浮动,防止margin重叠等)10 分钟理解 BFC 原理 - 知乎 (zhihu.com)

一、常见的定位方案

在讲BFC之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见的定位方案:

普通流(normal flow)

在普通流中,元素按照其在HTML中的先后位置自上而下布局,在这个过程中,

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/yuhongbei/article/details/119043095
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2023-01-03 21:55:26
  • 阅读 ( 200 )
  • 分类:面试题

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢