Blockquote 对象 Blockquote 对象代表着一个 HTML 引用(blockquote)块元素。 <blockquote> 标签定义摘自另一个源的块引用。 一个 <blockquote> 元素的内容通常展现为一个左、右两边进行缩进的段落。 在 HTML 文档中的每一个 <blockquote> 标签创建时,都会创建一个 Blockquote 对象。 from:
View Details在IIS中找到这个站点所用的程序池,点击“高级设置…” 在打开的列表中更改以下设置: 回收 固定时间间隔(分钟) 改为 0 虚拟/专用内存限制(KB) 改为 0 进程模型 闲置超时(分钟) 改为 0 from:bubuko.com/infodetail-1708029.html
View Details(或至少让其更难抓取) 这篇文章我翻译自:https://github.com/JonasCz/How-To-Prevent-Scraping,因为最近在看一些反爬的资料,无意间在 Github 发现这篇文章,我觉得写的很全面,所以想要翻译一下,顺便进行吸收。另外让我觉得非常赞的是这个文章从服务端和前端的角度都做了分析,我们应该从哪些点去做优化,而且每个点都举了例子,有些还给出了注意点。虽然文中有些提到的一些点很基础,也有很多我们目前在业务中也在使用,但是我还是从中吸收到了一些新东西,里面文中外部链接有很多,但是公众号这里不允许外链,所以大家可以点击文末最后的"阅读原文"到 Github 去查看,Github Markdown 的排版可能也比这里更好 : )。 (最后,有些仓促,可能有些注意不到的措别字,还请多多包涵) 提示:这篇文章是我 Stack Overflow 这个问题回答的扩展,我把它整理在 Github 因为它实在是太长了,超过了 Stack Overflow 的字数限制(最多 3 万个字,这文章已经超过 4 万字) 欢迎大家修改、完善还有分享,本文使用 CC-BY-SA 3.0 许可。 本质上说,防抓的目的在于增加脚本或机器获取你网站内容的难度,而不要影响真实用户的使用或搜索引擎的收录 不幸的是这挺难的,你需要在防抓和降低真实用户以及搜索引擎的可访问性之间做一下权衡。 为了防爬(也称为网页抓取、屏幕抓取、网站数据挖掘、网站收割或者网站数据获取),了解他们的工作原理很重要,这能防止他们能高效爬取,这个就是这篇文章的主要内容。 通常情况下,抓取程序的目的是为了获取你网站特定的信息,比如文章内容、搜索结果、产品详情还有网站上艺术家或者相册信息。他们爬取这些内容用于维护他们自己的网站(甚至通过你的内容赚钱!),或者制作和你网站不一样的前端界面(比如去做移动 APP),还有一些可能作为个人研究或分析使用。 实际上,有特别多的爬虫类型,而且他们的爬取方式都不太相同: 蜘蛛,比如 Google’s bot 或者网站复制工具 HTtrack,他们访问你的网站,而且在页面中寻找链接后递归的去爬取以获取页面的数据。有时候他们只用于获取特定数据,而不会全部爬取,通常结合 HTML 分析器在页面中获取想要的数据。 Shell 脚本,有时候,通用的 Unix 工具也被用来爬取:wget 或者 curl 用于下载页面,用 Grep (Regex) 去分析获取想要的数据,一般都会写一个 Shell 脚本。这些都是最简单的爬虫,也是最脆弱的一类爬虫(Don’t ever try parse HTML with regex !),所以是最早发现和防范的爬虫。 HTML 爬取器和分析器,会基于 Jsoup、Scrapy 还有其他一些工具。和 shell 脚本基于正则类似,他们呢基于特定模式(pattern)分析你的 HTML 结构从而获取想要的数据。 举个例子:如果你的网站有搜索功能,那这个爬虫可能会模拟提交一个搜索的 HTTP 请求,然后从搜索结果页中获取所有的链接和标题,有时候会构造有成千上百不同的请求,只是为了获取标题和链接而已。这是最常见的一类爬虫。 屏幕爬取,比如会基于 Selenium 或者 PhantomJS,他们实际上会通过真实浏览器打开你的网站,因此也会运行你网站的 JavaScript、AJAX 或者其他的,然后他们从你的页面获取自己想要的文本内容,通常: 基于浏览器的爬取很难处理,他们运行脚本,渲染 HTML,就像真实用户一样访问你的网站。 等页面加载完毕, JavaScript 也执行之后,从浏览器获取 HTML 结构,然后用 HTML 分析器去获取想要的数据或者文本。这是常见做法,所以有很多方法可以防止这类 HTML 分析器或爬虫。 […]
View Details索引 索引是什么 MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。 可以简单理解为排好序的快速查找数据结构。 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。 优缺点 优点 提高数据检索的效率,降低数据库的 IO 成本。 通过索引列对数据进行排序,降低数据排序的成本,降低了 CPU 的消耗。 缺点 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE 和 DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为 更新所带来的键值变化后的索引信息。 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间 的。 B-Tree 和 B+Tree 区别 B-Tree 的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+Tree 的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。 在 B-Tree 中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而 B+Tree 中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看 B-Tree 的性能好像要比 B+Tree 好,而在实际应用中却是 B+Tree 的性能要好些。因为 B+Tree 的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B-Tree 多,树高比 B-Tree 小,这样带来的好处是减少磁盘访问次数。尽管 B+Tree 找到一个记录所需的比较次数要比 B-Tree 多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中 B+Tree 的性能可能还会好些,而且 B+Tree 的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用 B+Tree 的缘故。 为什么 B+Tree 比 B-Tree 更适合实际应用中操作系统的文件索引和数据库索引? B+Tree 的磁盘读写代价更低 B+Tree 的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B-Tree 更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。 B+Tree 的查询效率更加稳定 由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。 索引分类 单值索引:即一个索引只包含单个列,一个表可以有多个单列索引 建表时,加上 key(列名) 指定 单独创建,create index 索引名 on 表名(列名) 单独创建,alter table […]
View Details为什么要做性能调优? 一款线上产品如果没有经过性能测试,那它就好比是一颗定时炸弹,你不知道它什么时候会出现问题,你也不清楚它能承受的极限在哪儿。 所以,要不要做性能调优,这个问题其实很好回答。所有的系统在开发完之后,多多少少都会有性能问题,我们首先要做的就是想办法把问题暴露出来,例如进行压力测试、模拟可能的操作场景等等,再通过性能调优去解决这些问题。 好的系统性能调优不仅仅可以提高系统的性能,还能为公司节省资源。这也是我们做性能调优的最直接的目的!所以,接下来我就给大家带来了一份“阿里巴巴lava性能调优实战(2021华山版)”想要学习的朋友们,我们就先来看看文章大概内容:(同时在文末会有笔记领取方式!大家自行解决) 主要内容 模块一 概述 为你建立两个标准。-个是性能调优标准,告诉你可以通过哪些参数去衡量系统性能;另-一个是调优过程标准,带你了解通过哪些严格的调优策略,我们可以排查性能问题,从而解决问题。 模块二 Java 编程性能调优 JDK是Java语言的基础库,熟悉JDK中各个包中的工具类,可以帮助你编写出高性能代码。这里我会从基础的数据类型讲起,涉及容器在实际应用场景中的调优,还有现在互联网系统架构中比较重要的网络通信调优。 03.字符串性能优化不容小觑,百M内存轻松存储几十G数据 05.ArrayList还是LinkedList?使用不当性能差千倍 06.Stream如何提高遍历集合效率? 10.网络通信优化之通信协议:如何优化RPC网络通信? 11.推荐几款常用的性能测试工具 模块三 多线程性能调优 目前大部分服务器都是多核处理器,多线程编程的应用广泛。为了保证线程的安全性,通常会用到同步锁,这会为系统埋下很多隐患;除此之外,还有多线程高并发带来的性能问题,这些都会在这个模块重点讲解。 12.多线程之锁优化(上):深入了解Synchronized同步锁的优化方法 13.多线程之锁优化(中):深入了解Lock 同步锁的优化方法 15.多线程调优(上):哪些操作导致了上下文切换? 17.并发容器的使用:识别不同场景下最优容器 模块四 JVM性能监测及调优 Java 应用程序是运行在JVM之上的,对JVM进行调优可以提升系统性能。这里重点讲解Java对象的创建和回收、内存分配等。 20. 磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型 21.深入JVM即时编译器JIT,优化Java编译 22.如何优化垃圾回收机制? 模块五 设计模式调优 在架构设计中,我们经常会用到-一些设计模式来优化架构设计。这里我将结合一-些复 杂的应用场景,分享设计优化案例。 29.生产者消费者模式:电商库存设计优化 30. 装饰器模式:如何优化电商系统中复杂的商品价格策略? 模块六 数据库性能调优 数据库最容易成为整个系统的性能瓶颈,这里我会重点解析-一些数据库的常用调优方法。 33.MySQL调优之事务:高并发场景下的数据库事务调优 35.记一次线上SQL死锁事故:如何避免死锁? 38.数据库参数设置优化,失之毫厘差之千里 模块七 实战演练场 以上六个模块的内容,都是基于某个点的调优,现在是时候把你前面所学都调动起来了,这里我将带你进入综合性能问题高频出现的应用场景,学习整体调优方法。 41.如何设计更优的分布式锁? 43.如何使用缓存优化系统性能? 最后 作者:努力向上的小芷 链接:https://juejin.cn/post/6920124384027885581 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details显式转换 其他数据类型转换成Number 将其他数据类型的值转化为数值时,有几种方法? Number() parseInt() parseFloat() +/- (一元操作符) 说一说上面方法的异同? 它们都是可以将非数值转化为数值,不同点如下:
1 2 3 4 5 |
1. Number() 可以处理Boolean、null、undefined,Object而parseInt不可以 2. 在处理字符串时 - number能处理数字字符串(正负),包括十六进制的数字以及空字符串; - parseInt是从第一个非空格字符开始解析,直到遇到一个非数字字符串,如果第一个不是数字或者负号,parseInt就会返回NaN 3. parseFloat()与parseInt()类似,+/-与Number()类似 |
规则 除以下情况外能正常转化为数字,其余全为NaN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
1. Boolean值, true--->1 false--->0 2. null--->0 3. 空字符串('')---> 0 4. 数字字符串('123', '1.23', '0xf')---> 123, 1.23, 15 5. 对象则是先调用valueOf方法,看该方法的返回值是否能转化成数字,如果不行则基于这个返回值调用toString方法,再测试改返回值能不能转化成数字 var a = { valueOf: function() { return 'xyxy'; }, toString: function() { return 1; } }; Number(a) // NaN |
其他数据类型转换成String 将其他数据类型的值转化为字符串时,有几种方法? 其他数据类型的值.toString() String(其它数据类型的值) 说一说上面方法的异同?
1 |
null与undefined上没有toString()方法 |
规则 字符串拼接时,加号两边如果出现字符串或者引用类型的值({}、[]、function(){}),都会变成字符串拼接(因为原本应该是把引用类型的值转为数字,但是需要先转为字符串,遇到字符串就直接变成字符串拼接了)
1 2 3 4 |
{} => "[object Object]" function(){} =>"function(){}" {}+0; //0 没有变成字符串拼接的原因:把{}当做块处理了,不参与数学运算 ({}+0); //"[object Object]0" 用括号运算符包起来就是数学运算了 |
1 2 3 4 5 6 |
// 做个题目吧 let result =10 + false +undefined+[]+'Tencent'+null+true+{}; //(10+0+NaN)+''+'Tencent' +'null' +'true' + '[object Object]' //"NaNTencentnulltrue[object Object]" console.log(result) |
其他数据类型转换成Boolean 将其他数据类型的值转化为布尔值时,有几种方法? ! 转换为布尔类型后取反 !! 转换为布尔类型 Boolean 规则?
1 |
只有 0、NaN、空字符串、undefined、null 五个值会变为false,其余都是true |
隐式转换 isNaN、Math方法
1 |
参考显式转换成Number的规则 |
+ 操作
1 2 |
两边的数据有一个是字符串类型则选用字符串拼接操作, 之后才是考虑数学计算的加操作 |
== 「类型一样的几个特殊点」
1 2 3 |
{} == {} : false 说明:对象(引用类型的值)比较的是堆内存的地址 [] == [] : false 同上 NaN == NaN : false |
2.「类型不一样的转换规则」
1 2 3 4 5 6 |
1. null == undefined : true 2. null、undefined和其他任何值都不相等即 在比较相等性之前,不能将null与undefined转换成其他任何职 3. 字符串 == 对象 要把对象转换为字符串 4. 剩下如果==两边数据类型不一致,都是需要转换为数字再进行比较 5.注意点: 虽然Number(null)的结果是0,但是null和0 ==比较时并不是转为数字比较的,即验证3中所说 |
作者:妍等等xy 链接:https://juejin.cn/post/6920236688224550925 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details今天逛博客网站 — shoptalkshow,看到这样一个界面,非常有意思: 觉得它的风格很独特,尤其是其中一些边框。 嘿嘿,所以来一篇边框特辑,看看运用 CSS,可以在边框上整些什么花样。 border 属性 谈到边框,首先会想到 border,我们最常用的莫过于 solid,dashed,上图中便出现了 dashed。 除了最常见的 solid,dashed,CSS border 还支持 none,hidden, dotted, double, groove, ridge, inset, outset 等样式。除去 none,hidden,看看所有原生支持的 border 的样式: 基础的就这些,如果希望实现一个其他样式的边框,或者给边框加上动画,那就需要配合一些其他属性,或是脑洞大开。OK,一起来看看一些额外的有意思的边框。 边框长度变化 先来个比较简单的,实现一个类似这样的边框效果: 这里其实是借用了元素的两个伪元素。两个伪元素分别只设置上、左边框,下、右边框,通过 hover 时改变两个伪元素的高宽即可。非常好理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="hljs-selector-tag">div</span> { <span class="hljs-attribute">position</span>: relative; <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#03A9F3</span>; &::before, &::after { <span class="hljs-attribute">content</span>: <span class="hljs-string">""</span>; <span class="hljs-attribute">position</span>: absolute; <span class="hljs-attribute">width</span>: <span class="hljs-number">20px</span>; <span class="hljs-attribute">height</span>: <span class="hljs-number">20px</span>; } &<span class="hljs-selector-pseudo">::before</span> { <span class="hljs-attribute">top</span>: -<span class="hljs-number">5px</span>; <span class="hljs-attribute">left</span>: -<span class="hljs-number">5px</span>; <span class="hljs-attribute">border-top</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">var</span>(--borderColor); <span class="hljs-attribute">border-left</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">var</span>(--borderColor); } &<span class="hljs-selector-pseudo">::after</span> { <span class="hljs-attribute">right</span>: -<span class="hljs-number">5px</span>; <span class="hljs-attribute">bottom</span>: -<span class="hljs-number">5px</span>; <span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">var</span>(--borderColor); <span class="hljs-attribute">border-right</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">var</span>(--borderColor); } &<span class="hljs-selector-pseudo">:hover</span><span class="hljs-selector-pseudo">::before</span>, &<span class="hljs-selector-pseudo">:hover</span><span class="hljs-selector-pseudo">::after</span> { <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> + <span class="hljs-number">9px</span>); <span class="hljs-attribute">height</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> + <span class="hljs-number">9px</span>); } } <span class="copy-code-btn">复制代码</span> |
CodePen Demo — width border animation 接下来,会开始加深一些难度。 虚线边框动画 使用 dashed 关键字,可以方便的创建虚线边框。
1 2 3 4 5 |
<span class="hljs-selector-tag">div</span> { <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> dashed <span class="hljs-number">#333</span>; } <span class="copy-code-btn">复制代码</span> |
当然,我们的目的是让边框能够动起来。使用 dashed 关键字是没有办法的。但是实现虚线的方式在 CSS 中有很多种,譬如渐变就是一种很好的方式:
1 2 3 4 5 6 |
<span class="hljs-selector-tag">div</span> { <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">90deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-x; <span class="hljs-attribute">background-size</span>: <span class="hljs-number">4px</span> <span class="hljs-number">1px</span>; <span class="hljs-attribute">background-position</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>; } <span class="copy-code-btn">复制代码</span> |
看看,使用渐变模拟的虚线如下: 好,渐变支持多重渐变,我们把容器的 4 个边都用渐变表示即可:
1 2 3 4 5 6 7 8 9 10 |
<span class="hljs-selector-tag">div</span> { <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">90deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-x, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">90deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-x, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">0deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-y, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">0deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-y; <span class="hljs-attribute">background-size</span>: <span class="hljs-number">4px</span> <span class="hljs-number">1px</span>, <span class="hljs-number">4px</span> <span class="hljs-number">1px</span>, <span class="hljs-number">1px</span> <span class="hljs-number">4px</span>, <span class="hljs-number">1px</span> <span class="hljs-number">4px</span>; <span class="hljs-attribute">background-position</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>, <span class="hljs-number">0</span> <span class="hljs-number">100%</span>, <span class="hljs-number">0</span> <span class="hljs-number">0</span>, <span class="hljs-number">100%</span> <span class="hljs-number">0</span>; } <span class="copy-code-btn">复制代码</span> |
效果如下: OK,至此,我们的虚线边框动画其实算是完成了一大半了。虽然 border-style: dashed 不支持动画,但是渐变支持呀。我们给上述 div 再加上一个 hover 效果,hover 的时候新增一个 animation 动画,改变元素的 background-position 即可。
1 2 3 4 5 6 7 8 9 10 |
<span class="hljs-selector-tag">div</span><span class="hljs-selector-pseudo">:hover</span> { <span class="hljs-attribute">animation</span>: linearGradientMove .<span class="hljs-number">3s</span> infinite linear; } <span class="hljs-keyword">@keyframes</span> linearGradientMove { 100% { <span class="hljs-attribute">background-position</span>: <span class="hljs-number">4px</span> <span class="hljs-number">0</span>, -<span class="hljs-number">4px</span> <span class="hljs-number">100%</span>, <span class="hljs-number">0</span> -<span class="hljs-number">4px</span>, <span class="hljs-number">100%</span> <span class="hljs-number">4px</span>; } } <span class="copy-code-btn">复制代码</span> |
OK,看看效果,hover 上去的时候,边框就能动起来,因为整个动画是首尾相连的,无限循环的动画看起来就像是虚线边框在一直运动,这算是一个小小的障眼法或者小技巧: 这里还有另外一个小技巧,如果我们希望虚线边框动画是从其他边框,过渡到虚线边框,再行进动画。完全由渐变来模拟也是可以的,如果想节省一些代码,使用 border 会更快一些,譬如这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="hljs-selector-tag">div</span> { <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#333</span>; &:hover { <span class="hljs-attribute">border</span>: none; <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">90deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-x, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">90deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-x, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">0deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-y, <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">0deg</span>, #<span class="hljs-number">333</span> <span class="hljs-number">50%</span>, transparent <span class="hljs-number">0</span>) repeat-y; <span class="hljs-attribute">background-size</span>: <span class="hljs-number">4px</span> <span class="hljs-number">1px</span>, <span class="hljs-number">4px</span> <span class="hljs-number">1px</span>, <span class="hljs-number">1px</span> <span class="hljs-number">4px</span>, <span class="hljs-number">1px</span> <span class="hljs-number">4px</span>; <span class="hljs-attribute">background-position</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span>, <span class="hljs-number">0</span> <span class="hljs-number">100%</span>, <span class="hljs-number">0</span> <span class="hljs-number">0</span>, <span class="hljs-number">100%</span> <span class="hljs-number">0</span>; } } <span class="copy-code-btn">复制代码</span> |
由于 border 和 background 在盒子模型上位置的差异,视觉上会有一个很明显的错位的感觉: 要想解决这个问题,我们可以把 border 替换成 outline,因为 outline […]
View Details