以下列举的,都是 JS 前端开发中最为常见的问题。知悉这些问题,不懂编程也能冒充前端大牛了。
目录
CSS 元素浮动的本质是什么?
浮动是 Html CSS 布局的关键知识点,不识浮动不算懂 CSS,真正了解了浮动,其它概念迎刃而解。
先看一个问题,在 Html 元素的渲染解析中,如何实现图片在文章中靠左显示?就像 Word 排版中的文字环绕效果:
解决方法就是给 HTML 标签添加一个 float CSS 属性,也就是浮动属性。对于容器,浮动让子元素按一个方向排行,例如“float:left”,让子元素按从左到右的顺序排列;对于元素,浮动让元素定位于父容器中的某一边或紧挨在某一个兄弟元素之后。
因浮动自动累加宽度,从而实现自适应大小的容器或按钮,这是浮动的价值。
但在子元素使用了浮动以后,父容器可能因子元素浮动而丧失高度。如下所示:
在上图中,左图像与右文本是有高度的,但因为使用了浮动属性,致使其父容器——即最上面的蓝色 div 的高度为 0。
使用 clear CSS 属性可以解决这个问题。最常见的用法,是在容器的尾部添加空标签,这个标签具有 clear 样式,如下所示:
<style>
.clear {
clear: both;
}
</style>
<div class="news">
<img src="news-pic.jpg" />
<p>some text</p>
<div class="clear"></div>
</div>
在上面的代码中,倒数第 2 行即是一个带有clear样式的空标签。也可以使用 <br class="clear"> 或 <hr class="clear">,甚至附有 clear 样式的 ::after 都可以。clear 样式的意义,在于重置浏览器的渲染光标,使原本被忽略计算的浮动元素的高度,重新计算进来。clear 样式最常用的属性值是“clear: both”。
float不但可以从左向右浮动(float:left),还可以从右向左浮动(float:right),以此实现自适应内容的左对齐、或右对齐布局。但如果仅是实现左对齐布局,有另外一个 CSS 样式同样可以达到:display:inline-block。inline-block 的意义是子元素以块元素方式,从左向右依次排列。使用这种方式,不需要使用 clear 清除浮动。
在浏览器布局中最常见的麻烦是浏览器兼容。在 IE6 浏览器中,如果将一个容器标签设置浮动,同时设置了 margin-left、margin-right 为10px,那么实际两边的间隙就是 20px。解决方法也很简单,给容器标签添加“_display:inline”样式。注意,这个带前置下划线的 _display 只有IE可以解析,其它浏览器会忽视。这是 CSS 作为描述性语言的优势,谁听懂谁翻译,听不懂没关系。
经典三栏式布局是如何实现的?
经典三栏布局效果是这样的:
left 与 right 区域是固定宽度,center 区域随浏览器窗口大小而变化,内容自动向下伸拉。这是前端网页开发的入门式布局,实现起来也相当简单。
总体来讲,是以浮动 + 相对定位实现的。以下是 Html 代码:
<div id="header">#header</div>
<div id="container">
<div id="center" class="column">#center</div>
<div id="left" class="column">#left</div>
<div id="right" class="column">#right</div>
</div>
<div id="footer">#footer</div>
因为 center 区域要随浏览器动态伸拉,所以它的宽度是 100%,给左右两个边栏留出的宽度是靠父容器的 margin-left、margin-right 样式设置的。代码如下所示:
#container {
padding-left: 200px; /* LC width */
padding-right: 150px; /* RC width */
}
#center {
background-color: #e9e9e9;
width: 100%;
}
实现这个布局效果的最关键代码在于左、右边栏元素的 margin-left、margin-right 属性。如下所示:
#left {
width: 200px; /* LC width */
margin-left: -100%;
right: 200px; /* LC width */
}
#right {
width: 150px; /* RC width */
margin-right: -150px; /* RC width */
}
左边栏元素设置“margin-left: -100%”,相当于在center区域的左边框折返,所以“right: 200px”样式的设置效果,是紧挨 center 左边框向左延伸 200 个像素。右边栏设置“margin-right: -150px”样式的效果,是以 center 右边框向右延伸 150 个像素。
浮动是在 columns 类名上设置的:
#container .columns {
float: left;
position: relative;
}
每栏都有浮动,并且使用相对定位,所以上面才可以对它们进行 margin 关系定位。
一般前端网页优化的关键点
文件合并
最简单的使用 webpack 打包。webpack 是一个前端开发中普通使用的文件模块化(此模块化与 JS 模块化不是一个概念)打包工具,可以将多个文件打包成一个文件,从而减少网络请求。使用方法也很简单,通过 npm 安装 webpack,然后在项目根目录下创建一个配置文件 webpack.config.js,然后运行 webpack 工具就可以了。配置文件如下所示:
在上面的配置文件中,entry 是入口文件列表,output 是输出配置。
除了可以打包 JS 文件,webpack 还可以打包 css 文件、压缩 Html/JS/CSS 文件内容等。这些功能也是通过在配置文件中添加描述信息实现的。
除了 webpack,glup 也可以合并压缩前端文件。原理与之类似。
CSS 精灵图
在 CSS 中可能会引用很多图片,将这些图片合并成一个图片,就是 CSS 精灵图。原图在二维精灵图平面上都有自己的绝对定位和宽高。在使用时,使用 background-image 指向精灵图,使用 background-position 指定定位就可以了。
使用 webpack,可以将多张图片自动合并成精灵集,并输出一份匹配的 sass 样式文件。webpack 减去了设计师手动合图、排图、编写相应 CSS 样式的麻烦。
关于 sass
sass 是一种设计师使用的 css 编译工具,这种工具处理后缀名为 .sass 的文件,将它们编译为 css 文件。在 sass 文件中,可以使用变量、可以计算属性的值,如下所示:
$side : left;
.rounded {
border-#{$side}-radius: 5px;
margin: (14px/2);
}
使用 sass,可以显著提高设计师调试 UI 的效率。
延时加载 JS 文件
HTML 4.01 为 script 标签添加了一个新属性:defer,如下所示:
<script src="test1.js" defer="defer"></script>
有这个属性,代表该脚本不会影响页面的 HTML 构建,浏览器可以等页面解析完之后再来处理这个脚本。
还有一个属性:async,表明当前脚本文件可以异步加载,无需等待。一般用于处理外部网站脚本。如果没有这个属性,当外部网站网速很慢时,会非常影响浏览体验。
动静分离
将静态资源,JS、图片、样式表等统一放在一个二级域名下(一般是 static.xxx.com),而其它动态功能在主站域名下提供,这就是动静分离。这样做方便在静态站点上开启 CDN 加速,另外还可以避免在静态站点上使用 cookie。
避免无效的 404 页面
时间长了,网站越做越大,有些页面原来能访问,后来可能就无法访问的 404 页面了。浏览器并不知道哪个页面是 404 页面,对于曾经是 404 的页面,浏览器也不敢断定以后都是 404 页面。404 页面对用户来讲,体验不好;对搜索引擎来讲,也会因此降低收录权重。
解决的方法是,可以用 Go 语言写一个简单的爬虫工具,定时爬自己的网站,只要 Http 状态码返回 404 就记录下来。然后将 404 列表统一发给后端程序员处理。
除了 404 页面,与此同类需要注意的优化,是 img 标签的 src 属性为空,这也会造成浏览器发送空请求至服务器。也可以使用同样的检测工具,检测页面中哪些 src 属性没有值。这些 src 空值的情况,可能出现于某些动态页面的动态变量绑定中。
设置 Html 页面缓存(cache-control 与 expires)
cache-control 控制页面的缓存行为。expires 用于定义缓存过期时间,它接受一个 GMT 时间(格林尼治时间)。如果缓存未过期,浏览器将从本地缓存中拉取内容。
对于 cache-control 的值,no-cache 表示从来缓存,no-store 表示从不保存缓存或保存于浏览器临时文件夹中,public 表示任何情况下都可以缓存该资源,private 表示当前内容有用户权限缓存分别,max-age 表示希望接收一个不大于设定时间的资源。
Cache-Control 在使用时允许自由组合,例如:
Cache-Control: max-age=3600, must-revalidate
其中 must-revalidate 表示当前资源一定是向原服务器发去的请求,而非代理服务器上的缓存。
在 nginx 中,可以使用 expires 统一设置站点静态资源的缓存时间:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 3d;
}
开启 nginx gzip 压缩
在 nginx.conf 中使用如下信息开启 gzip 压缩功能:
gzip on;
gzip_disable "MSIE [1-6].";
gzip_types text/plain application/x-javascript text/css text/javascript image/jpeg image/gif image/png;
以上配置,可对静态页面、JS 文件、样式表文件、图片资源进行压缩。其中 gzip_disable 设置 IE6 不启用 gzip,因为 IE6 对gzip解包支持不好,会造成页面假死,影响用户体验。
在 nginx 中开启 Etag 设置
在 nginx 中开启 Etag,只需要一行代码:
http{
etag on;
}
使用 nginx -s reload 重启即可生效。开启 Etag 可以显著提高网站性能,但是这背后的机理是什么呢?
当浏览器向服务器第一次请求某网页时,服务器会返回一个 HTTP 状态 200,同时返回该页面的上次修改时间,格式如下:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
第二次访问同一个网页时,浏览器会自动向服务器访问,在该时间之后页面有没有改动,格式如下:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
如果没有改动,服务器会返回一个 HTTP 状态码 304(代表页面无变化)及一个空报文,避免重复加载。
但是服务器端判断 If-Modified-Since 的最小单位是秒,如果间隔小于1秒,服务器会误报;有时候服务器也不能精确取得文件的修改时间,致使误报等等,基于这些情况,HTTP/1.1 协议引入了 Etag。这可以理解为是一个网页文件的版本号,格式如下:
ETag: "50b1c1d4f775c61:df3"
浏览器第一次某网页时,服务器会返回一个 Etag。浏览器在第二次向服务器重复加载同一个网页时,会同时询问:
If-None-Match: W/"50b1c1d4f775c61:df3"
如果文件没有变化,服务器直接返回304状态码。
尽量减少 cookie
cookie 出现在每次网页请求的请求头中,适当控制可以有效降低报文大小。
路由跟踪测试
在 windows 上使用 tracert,在 mac 上使用 traceroute,用于检测从当前电脑端到达指定服务器经过哪些节点,观察哪些节点影响了页面加载速度,有针对性地优化。在 mac 上 trace 某度的截图如下:
关于 CSRF 网站攻击
CSRF 是 Cross Site Request Forgery 的简称,学名跨站请求伪造,主要通过伪造登陆用户的 cookie 取得非法权限。用户登陆网站后会在本地留下 cookie,如果在未退出网站之前访问了一些非法站点,这些 cookie 信息可能就被不法分子利用干一些坏事情。有时候爬虫工具也会伪造 cookie,以便抓取只有登陆用户才能抓取的页面信息。
防范 CSRF 最普通的手段是使用 HTTPS 通讯协议,并在请求头 Header 中放置一个自定义的验证字符串。当用户登陆网站时,服务器生成 token、将 token 保存至数据库并返回给客户端,客户端在本地保存并在下一次发出网络请求时在报文中带上该 token。如果超时,或者收到的 token 与库中不一致,服务器视为请求无效。
该验证手段在 App 开发、小程序开发中也经常用到。
2019年1月21日于北京
参考资料