前端最佳开发实践

《web前端开发最佳实践》

高效前端开发综述

前端开发包括前端UI和后端数据的交互都属于前端开发的范畴。

Web前端开发需要具备的技能

\1. 页面标记(HTML)

\2. 页面样式

\3. 前端编程(JavaScript)

\4. 跨平台,跨浏览器

\5. 前端框架(jQuery)

\6. 调试工具

\7. 沟通能力

<div id="slideshow">
        <div class="current"><img src="./images/p1.gif" width="189" height="176" />div>
        <div class="current"><img src="./images/p1.gif" width="189" height="176" />div>
        <div class="current"><img src="./images/p1.gif" width="189" height="176" />div>
div>
<div>
    <br/>
    <a href="./glid/gywm/">关于我们a>
    <br />    
div>

上面的代码,第一段代码中的img外的div标签可以省略,img标签内的width和height属性可以通过统一的css代码设置,img标签需要添加alt属性来说明图片的信息,依靠br来增加距离是不和语义的做法,应该通过css样式来设置。因此,以上两端代码可以简化为:

<div id="slideshow">
        <img src="./images/p1.gif" class="current" alt="img info" />
        <img src="./images/p1.gif" alt="img info" />
        <img src="./images/p1.gif" alt="img info" />
 div>
    
<div>
    <a href="./glid/gywm/">关于我们a>
div>

此外,站点中的css样式和JavaScript脚本文件,可以分别压缩合并样式文件和脚本文件,在缩小文件大小的同时也减少了文件的HTTP请求次数,提高了性能。

web前端的代码规范主要针对的是HTML,CSS和JavaScript代码。

1.符合标准

W3C制定的标准包括使用语言的规范,开发中使用的原则和解释引擎的行为,主要由三个部分组成:结构标准,表现标准和行为标准。

2.格式规范统一

前端代码的格式主意包括命名,代码缩进,空格和空行的使用以及代码注释。 命名主要有HTML元素的id和class名,JavaScript中函数和变量的命名;HTML,CSS和JavaScript代码中都是通过代码的缩进来体现代码的层次关系;空格和空行主要是用在css和JavaScript代码中,用来提高代码的可读性,如操作符前后添加空格,不同代码逻辑之间添加空行;

3.高性能

前端性能体现在浏览器的响应速度上,包括网页的加载速度和页面的交互响应速度。

网页加载所占用的时间包括后端处理请求的时间,代码文件从服务器端传输的时间,HTML和css的组合展现的时间以及JavaScript加载和运行的时间。

减少文件传输时间的最直接的方式就是减小文件的大小,越少的代码文件相对传输就会更快;简洁和符合标准的HTML和CSS代码能减少浏览器解析的时间,加快浏览器渲染过程;页面中请求数量越少相对页面加载时间也会越快;在JavaScript代码中选择性能更好的实现方案,延迟加载,动态加载等技术会让页面加载更快和交互更流畅。

4.高安全性

前端安全问题如:跨站点攻击,cookie劫持,这些攻击通过设置JavaScript变量,HTML标签的值和属性,css属性值等方式伪造恶意代码来达到攻击的目的。

高效web前端开发

前端代码的结构组织和文件的命名

1.代码文件组织结构

常用的前端文件的组织结构:
js(防止JavaScript代码)
	lib(放置框架JavaScript文件)
	custom.js
css(防止css样式代码)
	lib(放置框架css文件)
	images(放置用于样式中的背景图)
	reset.css(统一元素默认样式的样式文件)
	custom.js(业务相关样式文件)
resource(放置页面图片文件以及其他类型资源文件)
index.html

2.代码文件的命名

代码文件的细化会使代码文件的数量增多,相应地进行网站加载时请求的数量也会增加,这样会导致网页整体的加载时间变长。 发布时需要合并相应的代码文件。工具有web Optimization,YUI Compressor。

代码文件的命名原则主要是名称需要表明文件对应的模块内容,对应的版本号和文件的格式。

前端代码重构

重构指的是在不改变代码外部行为的情况下进行源代码修改,重构之前需要考虑的是如何才能保证外部行为不改变。

1.删除无用代码,精简代码。无用的代码主要集中在css和JavaScript文件中,包括已经不起作用的css样式和废弃的JavaScript函数。

2.前端代码规范化。页面的HTML标签中有大量的css样式

页面head部分也有css样式,需要把这些css放到独立的文件中。调整代码的层次缩进格式。更改标准已不推荐的标签,在JavaScript中集中定义局部变量,并把部分全局变量转变为局部变量,缩小变量的作用域。

3.整理基础类库。统一UI插件的 使用,统一基础方法的使用。

4.前端代码模块化。按照模块归类css代码,定义模块不同的命名空间,将公共方法归类到独立的共通文件中,明确共有接口和私有接口。

5.提高页面加载性能。将部分不影响首页展示的JavaScript文件延迟到页面加载后加载,删除页面中初始隐藏的区域,改为通过JavaScript动态生成;页面中的部分图片延迟加载;调整css的JavaScript文件的引用顺序,即css在前JavaScript在后,给静态文件设置缓存,使用CSS Sprite,合并首页背景图;合并和压缩发布后的css和JavaScript代码文件。

重构前一定要预估风险,如果没有足够的自动化测试工具,最好先完善自动化测试代码。

重构的目的和范围要明确,切忌盲目修改。前端代码重构主要是提高代码的可维护性,可读性和性能。

最好是先易后难,循序渐进。首先修改诸如命名,格式等不涉及具体逻辑的内容,然后考虑模块化和性能提升等与具体逻辑相关的内容。

重构过程中要持续测试,在多个浏览器中测试,确保重构的部分功能正确。切忌在大量的重构之后进行测试,因为重构之后很难记清楚重构的逻辑,又可能遗漏部分测试用例。

如果是性能提升,要事先检测网站的整体性能并化量,找出性能瓶颈。重构过程中要持续监控性能,并对比性能提升的效果。

合理使用前端框架

选择前端框架,需要考虑的因素:

1.项目的需求

项目是否有AJAX操作?数据传输格式是josn还是xml?需要支持的浏览器?是移动应用还是网站?有哪些主要UI模块?常用的UI模块有模态窗口,滑块控件,进度条,提示框,分割框,幻灯显示以及自动填充模块。

2.项目的特点

开发周期

3.框架的特点。

多浏览器测试:多测试,早测试

1.IE7,IE8的兼容

2.HTML5的兼容

  1. 编写高质量,标准的HTML
  2. 明确支持的浏览器范围
  3. 尽量避免出现浏览器兼容问题
  4. 使用HTML5新特性时做好平稳降级
web前端代码开发和调试

web前端集成开发环境(IDE)

推荐两个强大的IDE:Aptana Studio和Webstorm。

web前端代码调试

IE Dev Toolbar

chore Developer Tools

Firefox Firebug

web前端性能分析

常用的web前端性能分析工具有YSlow,PageSpeed

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ev0tSkv9-1576226824848)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1574071062546.png)]

代码和资源的压缩与合并

1.web服务器开启Gzip压缩

在HTTP中允许客户端可以选择从服务器上下载压缩的内容,Gzip就是其中一种支持的格式。服务器启用Gzip压缩后,代码文件有更小的体积,尤其是文本文件。

web服务器开启Gzip压缩后,会在Response的header中增加Content-Encoding:gzip。可以通过检查此项header项来判断服务器是否开启了Gzip压缩。

2.JavaScript代码压缩

JavaScript压缩的原理一般是去掉多余的空格回车,替换长变量名,简化一些代码写法等。JavaScript代码压缩工具有很多。UglifyJS ,YUI Compressor和Closure Compiler。UglifyJS 不仅是压缩工具,同时具有JavaScript语法分析和代码美化功能。

3.CSS代码压缩

CSS代码压缩原理和JavaScript代码压缩的原理类似,去掉不必要的空格,回车,注释。

工具CSS Compressor和YUI Compressor

4.HTML代码压缩

压缩HTML代码仅仅是去掉空格,回车,注释等无关字符,并不会简化HTML代码本身。

5.图片资源压缩

TinyPNG工具压缩PNG格式图片,使用JPEGmini压缩JPG格式图片。目前留下的前端自动化构建工具Grunt

前端代码基本命名规范和格式规范

HTML命名规范

HTML带啊吗所有的标签名和属性应该都为小写。属性值使用双引号闭合。

<img src="demo.jpg" alt="test" />

给所有的关键元素定义元素的id和class,便于和css,JavaScript交互。id名称中的关键词用下划线(_)连接,class的关键词用中划线(-)连接。



<div id="reader">
    <div id="reader_introduce" class="reader-introduce">
        ...
    div>
div>

如果class名称仅作为JavaScript调用的“钩子”,则可在名称中添加“js”前缀。



<ul id="js_reader_menu">
    <li class="menu-toc js-active">TOCli>
    <li class="menu-store js-active">Storeli>
    <li class="menu-library">Libraryli>
    <li class="menu-news">Newsli>
ul>

HTML代码的层级缩进为4个空格。如果元素包含子元素,则此元素对应的起始标签和闭合标签分别单独占用一行。


<ul>
    <li>item1li>
    <li>item2li>
    <li>item3li>
    <li>item4li>
ul>
<body>
    
    <div id="reader_header">
        ...
    div>
    
    <div id="reader_content">
        ...
        
        <ul id="reader_content_toc">
            
        ul>
    div>
    
    <div id="reader_footer">
        ...
    div>
body>
CSS命名规范及格式规范

CSS类的命名规则和元素的id命名规则相似,只是组成类名称的关键字连接符为中划线(-)

.reader-content-title{
    ...
}
/* 为了避免class命名的重复,命名时取父元素的class名作为前缀 */

/* 父元素的样式声明 */
.reader-content{
    ...
}
/* 子元素的class名称以父元素中的class名称作为前缀 */
.reader-content-body{
    ...
}

在css样式定义中,左大括号放置在选择器的同一行,并和选择器之间添加一个空格分隔

/* css样式定义中的左大括号放置在选择器的同一行;样式声明中属性名称和值之间用一个空格分隔 */
.reader-content-title{
    background: #FFF;
    ...
}

多个选择器具有相同的样式声明时,每个选择器应该独占一行,便于阅读和维护。

/* 多个选择器具有相同的样式声明时,每个选择器应该独占一行 */
h1,
h2,
h3 {
    font-weight: normal;
    line-height: 1.2;
}

样式声明的顺序按字母顺序排列,不考虑浏览器前缀。

/* 样式声明的顺序按字母顺序排列 */
.reader-content-title{
    background: #FFF;
    border: 1px solid;
    -moz-border-radius: 4px;
    border-radius:4px;
    color: black;
    text-align:center;
}

样式定义按照模块来分组,相同模块的样式定义放在一起,不同模块的定义之间用一个空行分割。

/* reader herader */
.reader-header-title{
    ...
}
.reader-header-introduce{
    ...
}

/* reader footer */
.reader-footer-copyright{
    ...
}
.reader-footer-links{
    ...
}

CSS样式文件中添加注释主要有两种类型:文件头部的文件信息注释和正文中的解释说明注释。文件信息包括文件版本,版权信息及作者。

JavaScript命名规范及格式规范

JavaScript局部变量命名采用首字母小写,其他单词首字母大写的方式。命名时建议采用有意义的单词命名。不推荐使用标识变量类型的前缀。如int,str,obj等,不推荐使用单词缩写命名,变量以缩写命名降低了其可读性。

// 变量命名语义明确
var bookmarkDefaultTitle = 'Untitled Bookmark';

JavaScript的面向对象编程,会有公有或私有接口的概念。原则上公有接口的命名为首字母大写,私有接口的命名为首字母小写。

Reader.Content = function(){
   //私有变量
    var info,title;
    //私有方法
    var getContent = function(){
     ...   
    }; 
         return{
            //公有方法
            SetTitle:function(contentTitle){
                title = contentTitle;
            },
             //公有属性
             ContentInfo:info
        }
}();
            
        

jQuery框架类型变量添加“$”作为前缀。

var $tocTitle = $('.reader-toc-title');

左大括号应该在行结束位置,不应该单独一行。

//在左大括号应该在行结束位置,不应该单独一行
for (var i=0; i<100; i++){
    doSomething(i);
}

//应该一直使用大括号起逻辑块,即使逻辑只有一行
var isFound  = false;
if (statement){
    isFound = true;
    }

JavaScript中可以使用单引号或者双引号定义字符串,但是因为习惯于定义HTML的元素属性值时使用双引号,而

var content = '...';

//空格提高代码的可读性
doSomething(myChar,0,1);

while (x == y){
    ...
}

JavaScript语句结束时应该添加一个分号。

HTML最佳实践

标准的HTML代码

标准的HTML代码指的是html代码符合W3C标准。

验证代码是否符合标准

1.标准的页面会保证浏览器正确地渲染

2.网页能更容易被搜索引擎搜寻,提高网站的搜索排名

3.提高网站的易用性

4.网页更好的维护和扩展

HTML Validator,它是一个Firefox浏览器地插件,查看页面地同时验证页面。

标准地HTML页面结构

   


<link rel="stylesheet" type="text/css" href="my_style.css" />


<meta name="description" content="一个展示HTML页面的例子" />


<a href="/news">Newsa>
<img src="green.jpg" alt="Green" />
<video src="tgif.vid" autoplay onerror="failed(event)">video>


  
<html>
    <head>
        <meta charset="utf-8" />
        <title>简单的页面title>
        <link rel="stylesheet" href="my_style.css" />
    head>
    <body>
        <h1>简单的页面h1>
        <p>这是一个连接<a href="demo.html">simplea>sample.p>
    body>
html>

正确闭合HTML标签

HTML中所有的自闭合标签:area ,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr.

停止使用不标准的标签和属性

1.标签没有实际的语义,仅仅是用于设置样式

不推荐使用单纯设置样式的标签如big,center,font,basefont等,应该通过css设置样式。

不推荐在标签中添加border,width,hetght等 样式属性。

不推荐使用 (闪动或者滚动),这两个标签的职能已经超出HTML本身,并且存在浏览器兼容问题。

2.让HTML标签具有更好的语义

不推荐使用显示黑体和斜体,推荐使用h和

推荐使用css样式定义font-weight和font-style让页面更简洁。

不推荐使用 (给文字添加删除线),推荐使用 来代替。

3.移除不常用的HTML标签

样式与结构分离
HTML和CSS的组合方式

1.在html页面中连接一个CSS文件(最佳实践)

 
<link rel="stylesheet" href="my_style.css" media="screen" />
<link rel="stylesheet" href="my.css" media="print" />

2.在HTML页面中内嵌CSS样式



<head>
    <style>
        body {...}
    style>
head>

3.在HTML标签中添加内联css样式

此方式是样式直接添加到元素的style属性中

<span style="color: green; background: transparent">greenspan>

4.在css样式文件中加载css样式文件(不推荐原因:引用的css文件不能同时并行下载,延长了页面的下载过程)

@import "mystyle.css";
@import url("mystyle.css");
添加JavaScript禁用的提示信息

标签常规的用法是当JavaScript不可用时显示提示信息。

<script type="text/javascript">
    //一些操作
script>

<noscript>
    <p>
        浏览器不支持JavaScript
    p>
noscript>

提示用户JavaScript已被禁用,并同时提供一个功能简单,不依赖与JavaScript的代替网站提供用户继续浏览,做到平稳降级。如在首页中,当脚本不可用时会提示用户,同时会提供一个不依赖于脚本的移动站点作为代替的站点。

百度首页在脚本被禁用时添加的代码

<noscript><meta http-equiv="refresh" content="0; url=/baidu.html?from=noscript"/>
noscript>
/* 脚本启用时对应的样式 */
.product{
    ...
}

/* 脚本不可用时,通过覆盖以上定义的样式或者添加额外的样式来设置不同的外观 */
        .no-js.product{
            ...
        }
添加必要的 标签放在html页面head中,主要用于表示网站。有四个属性:name,http-equiv,content和charset.

name属性表述页面文档的元信息,http-equiv设置hTTP请求指令,charset设置页面的字符编码

1.设置IE浏览器的兼容模式

<meta nttp-equiv="X-UA-Compatible" content="IE=8" />

<meta nttp-equiv="X-UA-Compatible" content="chrome=1" />
会在IE9及以下浏览器中激活chrome Frame,强制IE使用chrome Frame渲染页面。

2.设置页面在移动设备中的显示

<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1" />

3.设置IE浏览器的“固定网站”功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awNnJYkh-1576226824850)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1574306898951.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QN72k7jX-1576226824850)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1574306922964.png)]

高可读性的HTML

HTML语义化

标签语义化提高了代码的可读性,有利于阅读者理解代码对应的模块。

从页面展示的外观上看,高语义化的页面就是去掉css样式后页面仍能保持良好的外观,并且可正常阅读。

<div id="reader_main_action" class="reader-main-action">
    <span class="reader-action-library">aspan>
    <span class="reader-action-spliter">|span>
    <span class="reader-action-toc">bspan>
    <span class="reader-action-spliter">|span>
    <span class="reader-action-note">cspan>
    <span class="reader-action-bookmark">dspan>
    <span class="reader-action-highlight">espan>

div>


<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>简单的页面title>
    <style type="text/css">
        .reader-main-action .spliter {
            margin-left: 30px;
        }

        .reader-main-action .spliter:before {
            content:'|';
            line-height: 28px;
            font-size: 20px;
            color: #888;
            cursor: default;
           	text-indent: 0;
            float: left;
            margin: 0 -20px;
            
        }
        /*.reader-main-action li {
            text-indent: -9999px;
        	}*/  

    style>
head>
<body>
<ul id="reader_main_action" class="reader-main-action">
    <li class="reader-action-library">ali>
    <li class="reader-action-toc spliter">bli>
    <li class="reader-action-note spliter">cli>
    <li class="reader-action-bookmark">dli>
    <li class="reader-action-highlight">eli>
ul>
body>
html>

1.熟悉所有规范中的HTML标签,理解各标签的语义,在核实的地方使用合适的标签。

2.熟悉各标签上规范的属性,给HTML标签设置必要的属性


<img src="/img/loading.gif" alt="data loading..." />


<a href="" title="">a>

3.样式和结构分离

4.给空标签中添加隐藏文字,用于说明标签的实际功能

如何设置网页标题层级

1,在页面内容的标题部分使用标签

2,页面中只使用一个

标签

3,标签使用过程中不要跳级

4,不要单纯使用标签给内容设置样式

HTML代码只关注语义不关注其外观,所有页面的外观都应该通过CSS样式控制。

如何正确设计表单

网站中的用户登录,注册,用户调查等都是通过页面中的表单提交到网站服务器的。


<form action="/service/user" method="post">
    <table>
        <tr>
            <td colspan="2">登录td>
        tr>
        <tr>
            <td>用户名:td>
            <td><input type="text" name="userName" />td>
        tr>
        <tr>
            <td>密码:td>
            <td><input type="text" name="password" />td>
        tr>
        <tr>
            <td colspan="2">
                <input type="checkbox" name="staySingned" />
                点击登录
            td>
        tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Login" />
            td>
        tr>
    table>
form>

使用

标签布局会导致页面HTML代码臃肿

<form action="/service/user" method="post">
    <div>登录div>
    <span>用户名:span>
    <input type="text" name="userName" />
    <span>密码:span>
    <input type="text" name="password" />
    <input type="checkbox" name="staySigned" />
    <span>点击登录span>
    <input type="submit" value="Login" />
form>

去掉了用户布局的

标签,改用css样式实现元素的对齐和布局,遵循了样式和结构分离的原则。

<form action="/service/user" method="post">
    <label for="userName">用户名:label>
    <input type="text" id="userName" name="userName" />
    <label for="password">Password:label>
    <input type="text" id="password" name="password" />
    <input type="checkbox" id="staySigned" name="staySigned"/>
    <label for="staySigned">点击登录label>
    <input type="submit" value="Login" />
form>
标签用于表单的标题。使用标签的另一个优点是可以通过设置元素上的

disabled属性来禁用所包含的表单控件。

<form action="/service/user" method="post">
    <fieldset>
        <legend>登录legend>
        <label for="userName">用户名:label>
        <input type="text" id="userName" name="userName" />
        <label for="password">Password:label>
        <input type="text" id="password" name="password" />
        <input type="checkbox" id="staySigned" name="staySigned"/>
        <label for="staySigned">点击登录label>
    fieldset>
    <input type="submit" value="Login" />
form>

提高表单的易用性

1.使用标签,并设置标签的for属性

<input type="checkbox" id="keepSigned" name="keepSigned" value="" />
<label for="keepSigned">保持登录状态30天label>


<label>
    <input type="checkbox" id="keepSigned" name="keepSigned" value="" />
    保持登录状态30天
label>

2.给输入控件设置合适的水印提示

输入控件的水印提示可起到提示用户输入的辅助作用,比如,提示输入的字符长度限制,格式等。大部分主流浏览器已经支持了此属性(除了IE9及以下浏览器以外)

针对IE浏览器,推荐使用jquery-placeholder插件,此插件的原理是当原始的placeholder属性不起作用时,通过绑定输入控件的focus和blur时间来模拟placeholder属性原始的功能。

代码如下:

<input type="text" name="email" id="email" placeholder="[email protected]" />

3.如有必要,给输入控件设置tab顺序

给输入控件设置tabindex属性来设置输入控件的切换顺序
<input type="text" tabindex="2" />

4.使用HTML5中引入的表单控件

<form action="/sevice/user" method="post">
    <fieldset>
        <legend>登录legend>
        <label for="userName">用户名:label>
        <input type="email" id="userName" name="userName" placeholder="[email protected]" tabindex="1" required="true" />
        <label for="password">密码:label>
        <input type="text" id="password" name="password" placeholder="password" tabindex="2" required="true"/>
        <label for="staySigned">
            <input type="checkbox" id="staySigned" name="staySigned" tabindex="3"/>
            点击登录
        label>
    fieldset>
    <input type="submit" value="Login" tabindex="4" />
form>
精简HTML代码

精简HTML代码是建立在不影响页面HTML语义的基础上的,如下是主要的三个精简HTML的方式:

1.删除多余的容器

<div id="container-up">
    <div id="signin_logo">
        <img alt="" src="images/signin.png" />
    div>
    <span><a href="#">点击关闭a>span>
div>

如果没有特别设置外观样式,如上代码至少可以省略一个

<div id="container-up">
    <img id="signin_logo" alt="" src="images/signin.png" />
    <a href="#">点击关闭a>
div>

2.装饰性的元素使用css样式实现

​ 不严谨的代码可能是这样:

<a id="more-intro">点击此处<img src="down-arrow.PNG" />a>

通过css样式设置实现代码类似如下:

<style type="text/css">
    .moreIntro {
        background: url(down-arrow.PNG) no-repeat 450px -28px
    }
style>
   
<a id="moreIntro">点击此处a>

3.避免使用table布局

过时的块状元素和行内元素

常见的块状元素:div /p/table/ul/ol/h1~h6

常见的行内元素:span/img/a/em/input/select

积极拥抱HTML5

HTML5新特性的使用
使用HTML5中简化的定义方式

1.定义文档类型声明


此声明意味着在浏览器中页面会以标准模式渲染。

2.定义页面编码

<meta charset="utf-8">

3.样式和脚本文件

<link rel="stylesheet" href="/css/lib/base.css" />

<script src="jquery.mim.js">script>

当浏览器解析到如上代码时,会把对应样式作为css样式加载和解析,把对应脚本作为JavaScript脚本加载和解析

使用HTML5中的新标签和新属性

1.HTML5中的新标签

新标签主要分为三个部分:语义化标签,功能性标签以及新的输入控件类型。

如下,是一个符合HTML5规范的页面结构:

<body>
    <header id="header">header>
    <nav id="navigation">nav>
    <section id="main">section>
    <aside id="sidebar">aside>
    <footer id="footer">footer>
body>

2.HTML5中新增的标签属性

1.

script标签中有两个和脚本加载时机有关的属性,即async和defer。按照规范,这两个属性只有在script标签中设置了src属性时才起作用,因此两个属性不应该使用在内联脚本上。


<scrpt src="file.js" defer="defer">scrpt>

<scrpt src="file.js" async="async">scrpt>

属性defer的作用是让脚本后置加载,相当于把脚本放置于页面最后面加载和执行。

属性async的作用是让脚本异步加载和执行。

二者差别:设置async属性后不能保证脚本按照顺序加载和执行,脚本加载完成后会立即执行,而设置defer的脚本还是会按照原有的顺序执行。因此,若脚本执行之间有依赖关系,则不能使用async属性。若页面中有内联的脚本依赖与加载的脚本,则不适合使用defer属性。

可以使用async属性的场合也可以使用defer属性,在设置async属性时,推荐同时设置defer属性,这样,当浏览器不支持async属性时defer会起作用,从而最大限度的提高脚本加载执行的性能。

2.标签的target属性

此属性的作用是指页面标签的默认窗口,省去了在标签中定义target属性的麻烦。

<head>
    <base target="_blank">
head>

属性target设置为_blank,单机页面上的超链接时会在新窗口打开。

3.和中的placeholder,required及autofocus属性

placeholder对应的一个jQuery插件jquery-placeholder,使用方法很简单,如下:

$('input,textarea').placeholder();
    
    .placeholder(color:#aaa;)

4.标签上的自定义属性data-*

H5中添加了用于保存自定义数据的方式,同时也添加了对应的API:dataset。如下展示了自定义数据的定义和读取:

<ol>
    <li id="byond_sea" data-length="2mlls">Beyond The Seali>
    ...
ol>

对应的读取和设置数据的方式如下:

var beyondSea = document.getElementById('byond_sea');
//获取数据
beyondSea。dataset['length'];
//设置数据
beyondSea.dataset['length']='3mlls';

如下是使用jQuery API的例子:

<div data-role="page" data-last-value="43" data-hidden="true" data-options='{"name":"John"}'>div>

$("div").data("role") === "page";
$("div").data("lastValue") === 43;
$("div").data("hidden") === true;
$("div").data("options").name === "John";

在H5的规范中,有一些标签和属性已经有了部分变更,它们改变了原有的定义。

1.

这四个标签表示将包含的字符设置为斜体,黑体,下划线和小字体。若是给字符设置斜体,黑体,或者添加下划线,应该使用css样式。

2.

标签除了可以包含脚本代码之外,还可以包含用户自定义的数据块。

script包含的数据块有HTML模板,XML数据等。

不要使用H5中已废弃的标签和属性

移除的标签按照移除原因可以分为3类

1.标签仅仅是为了设置外观,没有任何语义,而且这些标签可以使用css代替。

设计的标签包括:basefont定义文档中默认字体颜色,大小。

big标签设置文本的大字体

center用于将文本居中

font标签用于设置文本字体的样式

strike标签定义加删除线文本

tt标签定义打字机文本

2.标签破坏了可用性

frame,frameset,noframes

3.标签很少被使用,能引起混淆或者是有更好的代替标签

acronym,applet,isindex和dir

列举不规范属性:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PDRQqSGb-1576226824852)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1575341138629.png)]

如何处理浏览器兼容问题

下面介绍一些页面中使用H5新标签的实践方法,目的是让H5中的新标签在版本较早的浏览器中也能得到有限的支持,不至于影响整个页面的使用。

1.让浏览器识别H5规范中的新标签。

IE8浏览器中还没有添加对H5新标签的支持,所以无法直接展现H5新标签中的内容。

IE8/7/6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持H5新标签,代码如下:

var e = "abbr,article,aside,audio,canvas,datalist,details,dialog".split(',');
var i = e.length;                                                            
while (i--){                                                                 
document.createElement(e[i])                                                 
}                                                                            
                                                                             
<!--浏览器支持新标签后,还需要添加标签默认的样式-->                                                
article,aside{display:block}                                                 

以上两段代码JavaScript和css代码就可以让IE8以下版本浏览器支持H5中的新标签。

最好的方式是直接使用成熟的框架,html5shim的使用方法很简单,在页面的head部分添加框架的引用即可:

<script src="http://html5shim.googlecode.com/svn/trunk/html5.js">script>

2.H5中新特性的向后兼容

检测浏览器是否支持H5新特性准确率较高的是Modernizr。

如:判断浏览器是否支持手势触摸,可以在JavaScript代码中检测Modernizr.touch的值。

Modernizr使用方法很简单,首先要在head部分引入框架JavaScript文件:

<script src="js/modernizr.min.js">script>

其次在标签中添加一个名为no-js的类:

如果浏览器没有禁用JavaScript,则浏览器加载页面后,标签中的类会动态替换和添加。加载后,标签类似如下:

<html class="js canvas .........cufon-ready">
    
html>

在css代码中,可以通过使用这些类添加向后兼容的代码。如下是一个使用多背景图的例子:

#nice{
    background:url(background-one.png) top left repeat-x;
}

.multiplebgs #nice{
    background:url(background-one.png) top left repeat-x,
    url(background-two.png) bottom left repeat-x;
}

3.音频和视频的兼容

要让浏览器可以播放元素上的音频,最佳方式是提供MP3和0gg-Vorbis两种格式,兼容代码如下:

<audio controls>                                                
    <source src="elev.mp3" type='audio/mpeg; codecs="mp3"'/>    
    <source src="elev.oga" type='audio/ogg; codecs="vorbis"'/>  
                          
                                 
audio>                                                        

要让浏览器支持视频格式,最佳方式是提供WebM和MP4两种格式的视频,兼容代码如下:

                                                                   
<audio controls>                                                  
    <source src="elev.webm" type="video/webm"/>                   
    <source src="elev.mp4" type="video/mp4"/>                     
                                                    
    <iframe width="480" height="360" src="http://www.baidu.com"   
            frameborder="0" allowfullscreen>                      
    iframe>                                                     
audio>                                                                                                                          

为了处理向后兼容,添加了一个网络视频的地址。还有其他方式,比如添加一个Flash的视频播放器。

css最佳实践

高维护性的CSS

html代码主要表达了页面的语义,而css代码则让页面中的HTML代码具有了漂亮的外观,让页面鲜活起来。

css样式可以定义在元素的style属性中,也可以定义在head部分,还可以定义在单独的css文件中。

如何高效的组织css代码

1,首先是组织css代码文件。

所有css都可以分为两类:通用类和业务类。

代码的组织应该把通用类和业务类的代码放置于不同的目录中。

css
	library
	reader
		common.css
		default.css
		ie-style.css
前端css代码目录结构示例

样式文件default.css的作用是重置元素的默认样式,目的是让元素在各浏览器中有统一的外观。

样式文件common.css中放置共通模块的样式和一些基础样式。

共通模块包括:页面对话框,提示框等组件,以及页面头部,底部,侧边栏等共通UI模块的样式。

基础样式包括:全局的页面布局设置,字体设置,背景和前景色,以及一些公有的class。

常见的一个公有class是用来设置文字不可见的,代码如下:

.text-hide{
    font:0/0 a;
    color:transparent;
    text-shadow:none;
    background-color:transparent;
    border:0
}

样式文件ie-style.css中放置了兼容旧版本IE浏览器的样式。

把兼容旧浏览器的样式放置在单独的文件中,在页面中使用IE浏览器独有的条件注释方法样式引用此文件。示例如下:


浏览器处理兼容问题的原则是:首先考虑是否有其他没有兼容的方案,其次才考虑如何兼容。

由于各种原因而不得不写一些额外的兼容代码,如果存在这样的额外代码,则应该放置在单独的文件中。

页面布局分为头部,主题,尾部3部分,则css样式文件至少分割为3个,按照对应的模块定义了3个css样式文件为:reader.header.css/reader.content.css/reader.footer.css

在开发过程中发现头部的图标和按钮操作项对应的css样式内容太多了,因此把这些操作项对应的样式独立了出来,定义了一个新的css样式文件:reader.header…action.css

按照功能模块划分代码文件只是为了方便在开发阶段的开发和维护。在发布的时候会使用工具把多个文件压缩合并成一个文件。

假如要定义一个如下图所示的外观:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMAMEXPO-1576226824853)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1575441708344.png)]

按照上述的规则,定义的css样式框架应如下:

/*定义最外框的父元素的样式*/
.reader-header-container{
    ...
}

/*定义最上面黑色背景的工具条的样式*/
.reader-header-bar{
    ...
}

/*定义工具条内部的3个可单击菜单项目的样式*/
.reader-header-bar li{
    ...
}

/*定义下部的主体工具栏的样式*/
.reader-header-main{
    ...
}

/*定义下部工具栏中最左边logo的样式*/
.reader-header-logo{
    ...
}
/*定义下部工具栏中间的5个图标按钮的外框的样式*/
.reader-main-action{
    ...
}
/*定义工具栏中图标按钮的共通样式*/
.reader-main-action li{
    ...
}

/*定义工具栏中分隔竖线的共通样式*/
.reader-main-action .spliter{
    ...
}

/*按照从左到右依次定义工具栏中5个图标按钮的样式*/
.reader-main-action .library{
    ...
}

使用Less和Sass可以帮助开发者编写出高复用性和高扩展性的CSS代码。

如下实例展示如何使用Less编写样式代码。

//Less
.rounded-corners(@radius:5px){
    border-radius:@radius;
    -webkit-border-radius:@radius;
    -moz-border-radius:@radius;
}

#header{
    .rounded-corners;
}
#footer{
    .rounded-corners(10px);
}

经过编译后最终产生的css样式代码为:
/*生成的css*/

#header{
    border-radius:5px;
    -webkit-border-radius:5px;
    -moz-border-radius:5px;
}
#footer{
     border-radius:10px;
    -webkit-border-radius:10px;
    -moz-border-radius:10px;
}
使用CSS Reset:统一浏览器显示效果

重置元素默认样式的方式称为CSS Reset技术。

重置样式代码,如下:

:link,:visited { text-decoration:none }
ul,ol {list-style:none}
h1,h2,h3,h4,h5,h6,pre,code{font-size:lem;}
ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input{ margin:0;padding:0}
a img,:link img,:visited img {border:none}
address {font-style:normal}

另一种版本的重置方案

*{margin:0; padding:0}

选择样式重置方案的过程中需要考虑的问题:

1.HTML5中的新标签

如果在项目中需要使用H5中新添加的标签,则重置某些标签的display样式,因为IE8/IE9中没有定义这些标签的默认样式。样式代码如下:

article,
aside,
details,
figure,
figcaption,
footer,
header,
hgroup,
nav,
section,
summary{
    display:block;
}

audio,
canvas,
video{
    display:inline-block;
}

2.padding,margin和border

标签在浏览器之间的差异主要是由这三个样式有关的默认样式产生。

html,body,div,span,applet{
    margin:0;
    padding:0;
    border:0;
    font-size:100%;
    font:inherit;
    vertical-align:baseline;
}

3.字体设置

address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var{
    font-style:normal;
    font-weight:normal;
}

h1,
h2,
h3,
h4,
h5,
h6{
    font-size:100%;
    font-weight:normal;    
}

abbr,acronym{
    border:0;
    font-variant:normal;
}

input,
textarea,
select{
    font-family:inherit;
    font-size:inherit;
    font-weight:inherit;
}

4.其他元素的样式重叠

重置列表项的样式:
li {
    list-style:none;
}

重置表格样式

table{
    border-collapse:collapse;
    border-spacing:0;
}

重置连接默认样式
a:link,a:visited{
    text-decoration:none;
}
给CSS样式定义排序

css样式排序是指按照一定的规则排列css样式属性的定义,排序并不会影响css样式的功能和性能。

1.按类型分组排序

著名web前端专家把css属性分为7大类:显示与浮动(Display&Flow)定位(Positioning)尺寸(Dimensions)

边框相关属性(Margins,Padding,Borders,Outline),字体样式(Typographic Styles),背景(Backgrounds),其他样式(Opacity,Cursors,Generated Content)。

可以把影响元素页面布局的样式如(float,margin,padding,height,width)等排到前面,而把不影响布局的样式(如background,color,font等)放到后面。

2.按字母序排序

按字母排序的规则是按照属性的首字母从A到Z排列,忽略浏览器前缀(如-webkit-,-moz-,-o-,-ms-)。

3.按定义长度排序

按照样式定义的字符长度排序。

推荐一款免费的css排序工具,CSScomb,下载CSScomb工具包,安装到WebStrom上,然后就可以直接使用。

css排序实践,归纳为四点:

  1. 对CSS样式排序
  2. 推荐按样式属性功能分组排序
  3. 推荐在CSS样式代码编写完成并准备嵌入的时候排序
  4. 使用如CSScomb等工具排序
合理利用css的权重:提供代码的重用性

CSS样式的6中基础选择器:ID选择器(#)类选择器(.)属性选择器(a[href=""]{})伪类选择器(:hover{} ::after{}),标签选择器(a{})通配符选择器(body *{})

后代选择器(.eader .title{}),子选择器(.reader>.title{}),相邻选择器(.reader+.title{})

什么是CSS权重?css权重指的是这些选择器的优先级,优先级高的css样式会覆盖优先级低的样式,优先级越高说明权重越高,反之亦然。

计算css的权重是有一定的规则的,css权重是通过如下规则计算的:

1.计算选择符中的ID选择器的数量(=a)

2.计算选择符中的类选择器,属性选择器以及伪类选择器的数量(=b)

3.计算标签类型选择器和伪对象选择器的数量(=c)

4.忽略全局选择器

按照规则,基础选择器具有这样的优先级:

ID > 类|伪类|属性 > 标签类型|伪对象 > 通配符

如果两个选择器的权重相同,则可依照”就近原则“来判断。

如何选择合适的选择器:

1.CSS样式中尽量不要使用ID选择器

按照规范,一个页面不允许使用两个ID,如果使用了ID选择器就意味着此样式只作用于一个元素。该样式没办法

重用与其他元素。

<style type="text/css">
        #test{
            font-size:40px;
        }
        #test span{
            color:#ccc;
        }
 style>

<div id="test">这是一段<span>重要的文字span><span>请不要删除。span>div>

若要把上面的“不要删除”标红,代码如下:

 <style type="text/css">
        #test{
            font-size:40px;
        }
        #test span{
            color:#CCC;
        }
       .important{
            color:#F00;
        }
  style>


<div id="test">这是一段<span>重要的文字span>,请<span class="important">不要删除。span>div>

但是,测试发现,并未变红,因为新加的important类选择器权重低,选择器#test span组合权重为101,而.important为权重为10,起作用的还是#test span。

如果要提高.important的权限,可以提高选择符的权重:

 /*方式1:添加ID选择器*/
       #test .important{
            color:#F00;
        }

/*方式2:选择important关键字*/
        .important{
            color:#F00 !important;
        }

方式1使样式无法继续重用,方式二的权重最高,无法再被覆盖。这俩中都不好。

其实可以在基础选择器中使用类选择器而不是ID选择器。

 <style type="text/css">
        .test {
            font-size: 40px;
        }

        .test span {
            color: #CCC;
        }

        span.important {
            color: #F00;
        }
  style>

<div class="test">这是一段<span>重要的文字span>,请<span class="important">不要删除。span>div>

2.减少子选择器的层级

减少选择器的层级的过程,也是降低选择符整体权重的过程。为了比卖你样式“污染”其他模块,就会添加额外的父选择器来限定样式的作用域。

3.使用组合的CSS类选择器

使用CSS选择器组合的方式,开发者可以不考虑CSS样式覆盖的问题,避开了计算 选择符权重的过程,提高代码的重用性。

<style type="text/css">
        .test {
            font-size: 40px;
        }

        .common {
            color: #CCC;
        }

        .important {
            color: #F00;
        }
style>

<div id="test" class="test">这是一段<span class="common">重要的文字span>,请<span class="important">不要删除。span>div>

CSS代码的兼容性:如何兼容IE浏览器

1.熟悉IE浏览器中常见的样式兼容问题

有兼容问题的IE浏览器主要集中在IE8及以下版本,但是因为IE6推出历史舞台,不考虑,只需要考虑IE7和IE8

2.分离样式兼容代码

最佳做法是集中管理兼容代码。在IE浏览器中使用条件注释,让不同的浏览器加载不同的样式文件以达到兼容代码和正常代码分离的目的。

em,px还是%

页面元素的尺寸(长度,宽度,内外边距等)以及页面字体大大小是和页面整体布局息息相关的,也买你布局的方式又是多种多样。

核心思想是将页面元素的尺寸和字体大小设置为相对值,及元素的尺寸及字体的大小是相对于父元素的,随父元素的改变而改变。

使用最广泛的三种尺寸和字体大小设置方式:

1.px

标识像素。像素是显示器上显示的一个个小点,在显示器上显示的东西都是以像素的形式呈现的。

以像素为计量单位等同于设置为绝对尺寸。

2.em

em是个相对单位,等同于元素上计算的字体大小值,如2em标识的大小等同于所应用元素上字体大小的两倍。

3.百分比

百分比是一个相对计算方式,相对于父元素尺寸来计算的。如父元素的宽度为50px,子元素的宽度若设置为50%,表示子元素的实际宽度为25px

如何设置元素的尺寸和字体的大小?

1.尽量设置相对尺寸

2.只有在可预知元素尺寸的情况下才使用绝对尺寸

3.使用em设置字体的大小

高性能的CSS

使用高效的CSS选择器

在css代码中,非内联的样式都是通过css选择器和页面中的元素关联的。

什么是高效的CSS选择器?能被浏览器快速解析和匹配的css选择器就是高效的选择器。

css选择器的匹配原理是从右到左匹配的。

css选择器定义的最佳实践遵循的原则是:

1.避免使用通配符

通配符使用 * 号表示,它用来匹配页面中所有的元素。

2.避免使用标签选择器及单个属性选择器作为关键选择器,举例如下:

.reference p.list div{
    font-style:italic;
}

.reference p.list [data-link="red"] {
    color:#F00;
}

3.不要在ID选择器前使用标签名

4.尽量不要在选择符中定义过多的层级,最好不要超过三层

使用高效的选择符,可以减少页面的渲染时间。

CSS相关的图片处理

1.不要设置图片的尺寸

利用样式缩放图片会带来CPU的额外计算过程,增加了图片在浏览器中的渲染时间,超出实际尺寸的图片,其网络传输过程中也会占用更多的带宽,增加下载时间。因此,在制作图片时,尽量按照实际需求的尺寸制作。

2.使用CSS“雪碧”图(CSS Sprite)技术

(CSS Sprite)技术,一般翻译为CSS精灵。它可将零散的背景图合并为一张大图,再利用CSS的

background-position进行背景定位。

(CSS Sprite)技术的使用,减少了网络的请求次数,提高了图片整体的加载速度。

(CSS Sprite)技术缺点:

1.开发过程繁琐

2.维护过程复杂

3.使用不当,则会导致性能问题

使用(CSS Sprite)技术的最佳实践

1.在项目后期应用CSS Sprite技术

2.合理组织“雪碧”图

3.控制“雪碧”图的尺寸和大小

4.合理控制背景图单元之间的距离以及背景图的位置

5.借助工具

CSS Sprite Generator。SpriteMe

减少css的代码量

1.定义简洁的css规则

2.合并相关css规则

3.定义简洁的属性值

4.合并相同的定义

5.删除无效的定义

其他CSS高性能实践

1.避免使用@import

2.避免使用IE浏览器独有的样式:图片滤镜和CSS表达式

图片滤镜的使用会在图片加载时阻塞浏览器的加载和渲染,增加内存

css表达式的作用是动态设置css属性,应该避免使用css表达式,建议使用JavaScript代码来实现。

CSS3相关最佳实践

查看浏览器的支持情况

查看浏览器兼容性的网站:caniuse.com,Click Chart

添加必要的浏览器前缀

在css中定义的浏览器前缀表示此定义只在特定浏览器中起作用,其中

chorme和Safari浏览器使用-webkit作为前缀

Firefox浏览器使用-moz作为前缀

IE浏览器使用-ms作为前缀

Opera浏览器则使用-o作为前缀

最佳实践方案:

1.使用工具来添加CSS属性定义的浏览器前缀

编码阶段不需要为CSS属性定义添加任何的浏览器前缀,可以在开发完成后使用工具来添加css属性定义的浏览器前缀。推荐工具:Prefixr。

Sublime Text编辑器中,使用Autoprefizer添加浏览器前缀。

2.借助css预处理技术,给css定义添加浏览器前缀。

css预处理技术指的是Sass和Less。提高代码的可维护性

3.不要过度添加浏览器前缀

4.添加css3标准属性定义

做好CSS3中新特性的兼容处理

开发者为了让那些不支持css3新特性的浏览器也实现相同的外观和行为,使用了各种技巧,如利用IE浏览器独有的filter样式和JavaScript代码来实现。

推荐一个如何有效的使用HTML5的建议网站:html5please

JavaScript最佳实践

高维护性的JavaScript

养成良好的编码习惯,提高代码的可维护性

JavaScript是一种弱类型的语言。

提高JavaScript代码可维护性的最佳实践方法:

1.避免定义全局变量或函数

定义一个全局变量和函数如下:

var length = 0function init () {...    
}

function action () {...
}

定义全局的变量和函数,会影响代码的可维护性。

1.把变量和方法封装在一个变量对象上,使其变成对象的属性,基本可以避免被其他变量覆盖。

var myCurrentAction = {
    length:0,
    init: function () {...
},
    action: function () {...
}

但是,也有弊端,所有变量和函数的访问都需要通过主对象来实现,如访问如上的length变量,就需要通过

myCurrentAction.length来访问。增加了代码的重复度和代码编写的复杂度。

2.把全局的变量包含在一个局部作用域中,然后在这个作用域中完成这些变量的定义以及变量使用的逻辑。

如:通过定义一个匿名函数实现:

(function () {
    var length = 0;

    function init() {...
    }

    function action() {...
    }
})();

在实际的业务中,模块之间会有交互,这时则可以使用return语句,返回需要公开的接口。如上述代码修改如下:

var myCurrentAction = (function () {
    var length = 0;

    function init() {...
    }

    function action() {...
    }

    return {
        init: init
    }
})();

经过如此调整,外部代码访问init()方法时,就可以调用myCurrentAction.init了。此方法即做到了代码逻辑的封装,又公开了外部需要访问的接口。

2.使用简化的编码方式

如下:使用复杂的方式创建对象和数组

//对象创建
var person = new Object();
person.age = 25;
person.name = 'dang';

//创建数组
var list = new Array();
list[0] = 12;
list[1] = 20;
list[2] = 24;

简易方式创建:

//对象创建
person = {age:25,name='dang'};

//创建数组
list = [12,20,24];

3.使用比较运算符=而不是

JavaScript有两组相等的运算符:=(严格相等)和 !(严格不等),以及相等== 和!==(不等)

=(严格相等)和 !(严格不等)会比较两个基础类型值是否相等,或者两个复杂对象是否指向同一个地址。

相等== 和!==(不等)会先进行比较值的类型转换,再把两个比较值的类型转换为相同类型后才会进行比较运算。

4.避免使用with语句

在JavaScript中国,with语句可用来快捷的访问对象的属性。with语句格式

with (object) {
    statement
}

with语句的原理是:JavaScript解析和运行时,会给with语句单独建立一个作用域,而和with语句结合的对象中的属性则成为了此作用域的局部变量,因此可以直接访问。,例如:

with (Math) {
    a = PI * r * r;
    x = r * cos(PI);
    y = r * sin(PI/2);
}

上面的代码和下面的代码实现的一样

a = Math.PI * r * r
x = r * Math.cos(PI)
y = r * Math.sin(PI/2)

5.避免使用eval

在JavaScript中,eval函数的用法,它会接收一个字符串参数,把字符串内容作为代码执行,并返回执行结果。

如下:

eval('obj.' + key );

//可以使用下标方法取得属性值
obj[key]

6.不要编写检测浏览器的代码

最佳做法是不要编写检测浏览器的代码,而是检测浏览器是否支持某个特定的功能。

针对特定浏览器的代码逻辑放置在单独的文件中,方便后期维护和移除。如:已经知道IE8及以下版本浏览器

不支持H5的新标签,如果要在页面上使用H5的新标签,则需要针对这些浏览器加入兼容代码。可以把兼容代码放在单独的文件中。

使用更严格的编码格式

严格模式主要是针对不合理的地方进行改进。如:禁用with关键字,防止意外的全局变量,函数中的this不再默认指向全局,防止函数参数重名,防止对象属性重名,更安全的使用eval。

严格模式已经得到除了IE8之外的大部分浏览器的支持。

启用严格模式,只需在代码中添加如下代码即可:

"use strict";

在不支持严格模式的浏览器中,如下代码会被当做普通的语句运行,不会产生副作用。

<script>
	"use strict";
    console.log("这是严格模式")
script>

<script>
    console.log("这是正常模式")
script>

使用严格模式时需要遵循的几条最佳实践:

1.不要在全局中启用严格模式,如下:

如下代码设置了全局严格模式,应该避免这样使用

"use strict";
function doSomething() {
    //这部分代码会运行严格模式
}
function doSomethingElae () {
    //这部分代码也会运行严格模式
}

最佳使用:

function doSomething() {
    "use strict";
    //这个函数中的代码会运行严格模式
}
function doSomethingElae () {
    //这个函数中的代码不会运行严格模式
}

如果想给大量的代码设置严格模式,实例如下:

(function () {
    "use strict";
    //其他代码
})();

2.在已有代码中谨慎使用严格模式

JavaScript代码检查工具,JSLintJSHint

事件处理和业务逻辑分离

处理鼠标拖动页面元素,事件处理函数对应的代码如下:

var move_while_dnd = function(e) {
    var lb = scheduler._get_lightbox();//取得元素
    
    //设置元素位置
    lb.style.top = e.clientY+"px";
    lb.style.left = e.clientX+"px";
}

这个函数是直接绑定到事件上的事件处理函数,函数会接收一个event对象参数,这个对象包含了事件的宿主元素及其他相关数据。这段代码中的业务逻辑和实践耦合紧密,不利于代码的复用。

好的做法是把事件处理和业务逻辑处理分离开来,业务逻辑处理代码中不需要调用任何event对象中的属性,而在事件处理的代码中则专门处理和事件相关的逻辑。比如:取得event对象上的信息,阻止事件冒泡,或者默认行为等。

var setLightBoxPosition = function (top, left) {
    var lb = scheduler._get_lightbox();//取得元素

    //设置元素位置
    lb.style.top = top + "px";
    lb.style.left = left + "px";
}

var move_while_dnd = function (e) {
    setLightBoxPosition(e.clientY, e.clientX);
};

上面这段代码,业务逻辑全部包含在setLightBoxPosition函数中,函数中的逻辑和事件处理没有任何的关联,也不依赖特定的事件处理,提高了代码的可维护性和可重用性。

配置数据和代码逻辑分离

JavaScript代码基本上都是由业务逻辑和数据组成,逻辑代码根据数据完成一定的操作。很多数据都是写死的,比如URL,显示在界面上的提示信息,页面元素相关的样式值及其他使用到的固定值,这部分无逻辑的数据可统称为配置数据。

如何把配置数据和代码逻辑分离?

1.把代码中的配置数据部分抽取出来。抽取的原则是这些数据在代码中是写死的,并且在后期有可能会变更。

把JSON格式的配置数据作为一个参数传给了一个函数,通过这个函数的处理,可以把参数保持在客户端。

如新浪微博,StackOverflow。

逻辑与结构样式分离

JavaScript中的一个强大能力是不仅可以访问页面的HTML元素,还可以修改或删除相关元素,在JavaScript中,这部分统称为HTML文档对象模型(HTML DOM)。

在编写JavaScript代码时,让JavaScript代码只关注逻辑行为,尽量不要越权做本HTML代码和CSS代码完成的工作,让逻辑与结构样式分离。

从JavaScript代码逻辑中分离CSS样式

在JavaScript代码中,可以通过设置元素的style对象,来修改元素的样式,如下示例通过JavaScript给元素设置了大量的样式。

var el = document.getElementById('main_container');
var list = el.getElementsByTagName('li');
for (var i=0,j=list.length;i<j;i++){
    list[i].style.borderColor = '#f00';
    list[i].style.borderStyle = 'solid';
    list[i].style.borderWidth = '1px';
}

也可以通过设置style伤的cssText属性,来设置元素的样式,比如上述代码可以改写为:

var el = document.getElementById('main_container');
var list = el.getElementsByTagName('li');
for (var i=0,j=list.length;i<j;i++){
    if(list[i].innerHTML === ''){
        list[i].style.cssText += 'border:1px solid #f00;';
    }
}

但是通过以上两种方式修改元素样式,都降低了代码的可维护性。

最佳做法是,在JavaScript代码中,仅仅是设置元素的Class。如上代码可修改为:

var el = document.getElementById('main_container');
var list = el.getElementsByTagName('li');
for (var i=0,j=list.length;i<j;i++){
    if(list[i].innerHTML === ''){
        list[i].classList.add('empty');
    }
}

然后在页面引用的CSS文件中添加一条CSS规则:

.empty {
    border:1px solid #f00;
}

如果遇到元素样式的修改,只需要修改元素上CSS对应的CSS代码。

从JavaScript代码逻辑中分离HTML结构

避免在JavaScript代码中生成大量的HTML元素及内容,提高页面HTML代码结构的可维护性。

在JavaScript中,可以通过多种方式生成元素,最常见的是通过元素的innerHTML属性设置元素内部子元素,代码如下:

var d2 = document.createElement("DIV")
d2.innerHTML = "";
d.appendChild(d2);

复杂点的,根据数据动态拼接HTML结构,如下:

var template = '
'; template += '
%title%
'
; template += '
%content%
'
; template += ''; var html = template.replace(/%\w+%/g,function(matchs){ return obj[matchs.replace(/%/g,"")] }); d.innerHTML = html;

以下是一些让HTML代码和JavaScript代码分离的解决方案

1.从服务器端动态获取HTML代码

将页面加载初始不需要加载的HTML代码从页面中分离,放置在单独的文件中。当需要显示这些内容时,再通过AJAX动态从服务器端获取,然后显示在页面上。或者把JavaScript模板放置于单独的文件中,需要时才从服务器端加载。

下面是从服务器端获取HTML代码的示例:

var xhr = new XMLHttpRequest();
xhr.open('GET',"content/templates/store.html",true);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        document.getElementById('store_container').innerHTML = xhr.responseText;
    }
};

xhr.send(null);

如果页面在引用了jQuery框架,则使用jQuery中提供的方法:

$('#store_container').load("content/templates/store.html");

使用AJAX技术动态获取html代码的另一个优点是减少了页面初始的html代码量,加快了页面的传输时间,减少了页面的解析时间。

2.通过客户端动态生成页面结构

把JavaScript模板代码放置在

<script id="main_info" type="text/x-tmpl">
     <li><b>${name}</b> (${class})</li>
script>

当需要取得模板代码时,通过innerHTML属性即可获取:

var infoTemplate = document.getElementById('main_info').innerHTML;
JavaScript模板的使用

从使用率来看,流行的JavaScript模板主要有:

1.Mustache

2.Underscore

3.Handlebars

推荐一个工具类网站,Template-engine-chooser

1.尽量不要在模板中滥用逻辑块

2.不要构建太复杂的模板

3.使用预编译模板

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExEJXxMm-1576226824855)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1575882678432.png)]

在JavaScript开发中应用MVC模式

MVC,它将程序设计分为三个部分:model层是数据层,view层是用户表现层,而controller是用户交互控制层。

一般来说,controller会从model层请求数据,在将数据经过处理后就会放到view层显示给最终用户。

在前端页面中,通过AJAX或者其他手段将从后端得到的数据进行一些处理并构成model层,而最终的css和生产的html以及一些细节的DOM操作构成了view层;

controller层主要关注具体业务,比如:和model交互,处理数据,验证数据,取得和保存数据,同时还会根据实际业务和数据操作view层,驱动view层展现页面给最终用户。

JavaScript模块化开发

按照不同的职责划分代码的层级,提高代码的可维护性。

根据业务或功能的不同对前端代码进行划分称为模块化开发。

模块就是指包含业务相关的方法和数据的组合,且模块之间实现松耦合,每个模块都有对外公开的接口,提供模块之前的相互调用。

按照模块的设计思想,在JavaScript中利用立即执行函数,可以实现在不暴露私有数据的前提下公开一些公共的接口,如下是模块的具体实现实例:

 var modulel = (function(){
            var length = 0;
            var init = function(){
                //...
            };
            var action = function(){
                //...
            };
            return {
                init:init,
                action:action
            };
 })();

这种方式避免了模块之间的代码“污染”,做到了模块的封装和接口的公开。

若模块之间存在很紧的依赖关系,则模块内部最好不要直接访问所依赖的外部模块,而是通过传参的方式传入模块:实例:

var modulel = (function($,module2){
            //...
})(jQuery,module2);

全局变量jQuery和模块module2 传入到了modulel中,而在模块内部又是使用了参数$和module2作为 jQuery和module2 在模块内部的引用,并没有直接使用全局变量jQuery和module2

JavaScript模块规范主要有两种:CommmonJS和AMD。二者主要差别是在加载模块的方式上,CommmonJS中以同步的方式加载模块,使用require()方法来加载模块。在AMD中是以异步方式加载模块。

如下是CommmonJS规范定义的方式加载math模块:

var add = require('math').add;
add(val,1);

AMD中是以异步方式加载模块,为了在加载时不影响后续的执行,在实现上使用了回调函数,将如上的代码写成AMD规范,如下:

 require('math',function(math){
            var add = math.add;
            add(val,1);
 });

目前实现AMD规范的JavaScript库主要由两个方面:requireJS和curl

合理使用AJAX技术

应用AJAX技术的一些实践方法:

1.明确AJAX技术的使用场景

适合使用AJAX技术的场景有:

  • 前端会根据用户需求动态取得后端数据,然后更新网页界面。
  • 期望通过不刷新页面而取得任何资源或页面。
  • 动态进行用户输入的验证

因为使用AJAX技术取得的任何数据都是动态的,所有如果没有添加额外的处理,AJAX的应用会破坏浏览器上的后退按钮,破坏搜索引擎的索引,并且会在任何禁用了JavaScript的场合失去作用。

2.借助成熟的AJAX框架,但不要忘记原生的AJAX使用方法

很多框架都提供了AJAX的接口,方便开发者使用。如jQuery,YUI,Dojo。

http://api.jquery.com/category/ajax介绍如何使用原生的AJAX的文章。

3.在AJAX操作过程中,做好和用户的交互

AJAX操作具有异步,以及操纵过程中页面无刷新的特色。如果用户在页面上做某些操作触发了一个AJAX请求,默认并不会立即有页面的响应。可能会造成操作体验,为响应的假象。

为了提高用户的体验,有必要在进行AJAX操作的过程中给用户适当的反馈。防止用户重复操作。

具体的方式:

在AJAX操作过程中禁用触发此操作的按钮,添加蒙版,合适的页面提示,加载一个动画等,告知用户操作进行中。

在AJAX操作失败添加一个提示

AJAX操作需要添加一个超时的限制,如果在限制时间内未完成,提醒用户超时操作终止。

4.使用JSON格式作为AJAX传输的数据格式

使用json格式能 比xml格式具有更小的数据量,而json也支持JavaScript原生。

5.使用合适的方案,弥补AJAX技术带来的缺陷

AJAX缺陷,浏览器不会记录AJAX请求的历史,不能通过单击后退按钮返回到AJAX请求之前的状态。

如果有需要,也有可能的方案,比如使用jQuery插件jquery-hashchange。此插件的设计思路时通过设置url上的hash值来实现浏览器浏览历史的保留,用户可以使用浏览器工具栏上的前进后退按钮来切换页面上的无刷新操作。

高性能的JavaScript

加快JavaScript文件的加载速度

从代码文件的角度说,加快JavaScript代码加载速度最有效的办法就是减少初始加载文件的体积和加载的次数。

前端代码的压缩合并可以降低代码文件的大小并减少文件请求的次数。还有延迟,异步加载和执行JavaScript代码。

延迟加载JavaScript文件的目的是避免代码的加载和执行过程阻止页面的解析。

推荐:尽量将JavaScript代码的引用放置在body的底部,让页面其他元素优先解析,JavaScript代码文件的加载和解析推迟到整个页面元素解析完成之后进行。

代码如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JavaScript文件引用title>
    <link rel="stylesheet" href="sample.css"/>
head>
<body>
    <p>sample textp>

    
    <script src="script1.js">script>
    <script src="script2.js">script>
body>
html>

可以使用script标签的属性:defer和async(推荐)

可以通过动态创建script元素的方式达到异步加载和执行JavaScript代码的效果:

var script = document.createElement("script");
script.type = "text/javascript";
script.src = "file.js";
document.getElementsByTagName_r("head")[0].appendChild(script);

JavaScript加载框架:如 HeadJS,RequireJS,LABjs

养成良好的编码习惯,提高代码运行速度

如下是一个缓存浏览器滚动条宽度的实例:


function getScrollbarWidth(){
    if (!scheduler.scroll_width){
        var outer = document.createElement("div");
        outer.style.visibility = "hidden";
        outer.style.width = "100px";
        document.body.appendChild(outer);

        var widthNoScroll = outer.offsetWidth;
        //强制显示滚动条
        outer.style.overflow = "scroll";
        //添加一个div
        var inner = document.createElement("div");
        inner.style.width = "100%";
        outer.appendChild(inner);

        var widthWithScroll = inner.offsetWidth;

        //删除div
        outer.parentNode.removerChild(outer);
        scheduler.scroll_width = widthNoScroll - widthWithScroll;
    }
    return scheduler.scroll_width
}

为了计算滚动条的宽度,需要动态插入一个元素在页面中,并在计算完成后移除此元素。

1.少用for-in循环

很多开发者把for-in用于对象的克隆,这不是一个好的做法,如果有大量的克隆操作,最佳方法是在clone函数中明确复制每个属性,如下

function clone(obj){
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    copy.foo = obj.foo;
    copy.bar = obj.bar;
    return copy;
}

2.谨慎使用eval

3.正确使用数组

4.正确的内存回收

浏览器回收“垃圾”的原则是回收那些不再访问的对象,在代码中正确的做法是尽量释放不需要的对象,具体方式如下:

尽量不使用全局变量,因为全局变量在页面的整个生命周期中不会被回收。

确保解除已经不需要的时间监听,如那些要移除的DOM对象上绑定的事件。

不要在闭包中返回外部不需要的对象

使用高性能的变量或属性值读取方式

JavaScript中的作用域和作用域链关系到代码执行的性能。

作用域的工作原理:

作用域就是变量或者函数的作用范围,JavaScript中最大的作用域就是全局作用域。如,全局的变量在运行环境的任何地方都可以访问到。

JavaScript中不存在块作用域,即一个大括号包含的区域不会成为一个单独的作用域,最小的作用域是函数。

一个函数不仅可以访问自己内部定义的变量,也可以访问到其外部函数或全局定义的变量。多个函数嵌套定义时,就会形成作用域包含的关系,这个关系称为作用域链。如下,是一个访问外部作用域变量的实例:

function update(){
    var imgs = document.getElementByTagName("img");
    for (var i=0,len=imgs.length;i<len;i++){
        imgs[i].title = document.title + "- image -" + i;
    }
}

一个变量在作用域链上查找的层级越多则读取的速度就越慢。函数中局部变量的访问是最快的。因为它处在作用域的最里层,而全局变量访问是最慢的,它处于作用域链的最外层。

上面的例子使用了多次相同的外部域变量,可以改写为:

function update(){
    var doc = document;
    var imgs = doc.getElementByTagName("img");
    for (var i=0,len=imgs.length;i<len;i++){
        imgs[i].title = doc.title + "- image -" + i;
    }
}

不推荐使用with,原因是with会形成一个作用域,加深上下文作用域链的深度。

正确使用try-catch表达式的示例如下:

try {
    //业务逻辑
}catch(ex){
    errorHandler(ex);
}

在JavaScript中,对象的构造函数中有一个名为prototype的对象,即为原型对象,这个对象上的属性或方法是共享给所有实例对象的,所以说,实例对象上的属性和方法来自于两个地方,自身和对应的原型对象。因为原型对象本身也可以是其他构造函数的实例对象,所以原型对象中的属性和方法也可能来自于其作为实例对象时对应的原型对象上。这就形成了一个由各个原型对象组成的链条,称为原型链。

原型链最顶端是构造函数Object中名为prototype的对象。查找对象的方法或属性时,首先会查找自身是否存在此属性或方法。如果未找到,则会继续在原型链上查找,直到找到或者未找到返回undefined值为止。

如下是一个原型的示例:

function Person(name){
    this.name = name;
}
Person.prototype = {location : 'china'};

var personA = new Person('name1');
var personB = new Person('name2');

alert(personA.location);  //china
alert(personB.location);  //china

在原型链上检索对象的属性或方法也会影响性能,在原型链上检索的局部变量越多,性能越差,即使是读取在对象上直接定义的属性也比读取局部变量慢。如下:

for (var i=0;i<numbers.length;i++){
    number[i] *= 2;
}

在整个循环过程中,会反复读取numbers的length属性值,性能改进是使用一个局部变量缓存此属性值,修改如下:

for (var i=0;len=numbers.length;i<len;i++){
    number[i] *= 2;
}

变量和对象属性或方法的读取会影响性能,尽量要将外作用域的变量或对象上的属性值缓存在局部变量中,以提高读取性能。

高效的DOM操作

DOM操作优化的总体原则是尽量减少DOM操作。

DOM操作对性能影响最大其实还是因为它导致了浏览器的重绘(repaint)和重排(reflow)。

简述浏览器的渲染原理:

从下载文档到渲染页面的过程中,浏览器会通过解析HTML文档来构建DOM树,解析css产生css规则树。JavaScript代码在解析过程中,可能会修改生成的DOM树和css规则树。之后根据DOM树和css规则树构建渲染树,在这个过程中,css会根据选择器匹配HTML元素。渲染树包括了每个元素的大小,边距等样式属性,渲染树中不包含隐藏元素及head元素等不可见元素。最后浏览器根据元素的坐标和大小计算每个元素的位置,并绘制到页面上。

重绘指的是页面的某些部分要重新绘制,比如颜色或背景色的修改,元素的位置和尺寸并没有改变。

重排指的是元素的位置或尺寸发生了改变,浏览器需要重新计算渲染树,导致渲染树的一部分或全部发生变化。

如下的这些DOM操作会导致重绘或重排:

增加,删除和修改可见DOM元素

页面初始化的渲染

移动DOM元素

修改css样式,改变DOM元素的尺寸

DOM元素内容改变,使得尺寸被撑大

浏览器窗口尺寸改变

浏览器重开滚动

如:请求下面的DOM元素布局信息:因为这些值都是动态计算的,所以浏览器需要尽快完成页面的绘制,然后计算返回值。

offsetTop / Left / Width / Height,

scrollTop / Left / Width/ Height,

clientTop / Left /With /Height,

getComputedStyle()或currentStyle.

降低重排或重绘带来的影响:

1.合并多次的DOM操作为单次的DOM操作

最常见频繁进行DOM操作的是频繁修改DOM元素的样式,如下:

element.style.borderColor = '#f00';
element.style.borderStyle = 'solid';
element.style.borderWidth = '1px';

如上的代码优化为:

//优化方案1
element.style.cssText += 'border: 1px solid #f00;';
//优化方案2
element.className += 'empty';

2.把DOM元素离线或隐藏后修改

  1. 使用文档片段

    文档片段是一个轻量级的document对象,并不会和特定的页面关联。通过在文档片段上进行DOM操作,可以降低DOM操作对页面性能的影响,代码如下:

    var fragment = document.createDocumentFragment();
    //大量基于fragment的DOM操作
    ...
    document.getElementById('myElement').appendChild(fragment);
    
  2. 通过设置DOM元素的display样式为none来隐藏元素

    var myElement = document.getElementById('myElement');
    myElement.style.display = 'none';
    //一些基于myElement的DOM操作
    ...
    myElement.style.display = 'block';
    
  3. 克隆DOM元素到内存中

    把页面上的DOM元素克隆一份到内存中,然后在内存中操作克隆的元素,在内存中操作克隆的元素不会引起页面上的性能损耗,代码如下:

    var old = document.getElementById('myElement');
    var clone = old.cloneNode(true);
    //一些基于clone的DOM操作
    ...
    old.parentNode.replaceChild(clone,old);
    

3.设置具有动画效果的DOM元素的position属性为fixed或absolute

把页面中具有动画效果的元素设置为绝对定位,使得元素脱离页面布局流,从而避免的页面频繁的重排。

4.谨慎取得DOM元素的布局信息

for (for i=o;i<len;i++){
    myElements[i].style.top = targetElement.offsetTop + i*5 + 'px';
}

上述代码中,会在一个循环中反复取得一个元素的offsetTop值,优化是在循环外部取得元素offsetTop的值。

var targetTop = targetElement.offsetTop
for (for i=o;i<len;i++){
    myElements[i].style.top = targetTop + i*5 + 'px';
}

5.使用事件托管方式绑定事件

利用事件冒泡机制,只在父元素上绑定事件处理,用于处理所有子元素的事件,在事件处理函数中根据传入的参数判断事件源元素,针对不同的源元素做不同的处理。

//获取父节点,并添加一个click事件
document.getElementById('list').addEventListener("click",function(e){
    //检查事件源元素
    if(e.target && e.target.nodeName.toUpperCase == "LI"){
        //针对子元素的处理
        ...
    }
})

上述代码中,只在父元素上绑定了click事件,当点击子节点时,click事件会冒泡。父节点捕获事件后通过e.target检查事件源元素并作出相应处理。

jQuery中可以使用如下方式实现事件的托管

$("table").on("click","td",function(){
	$(this).toggleClass("chosen");
});
使用辅助工具优化JavaScript代码性能

在优化JavaScript代码时,首先要整体评测性能并找到性能的瓶颈,这样才能由针对性地优化那些对性能影响最大的部分。

在做JavaScript代码性能优化时,首先是查看JavaScript代码文件的加载情况。工具推荐PageSpeed,YSlow

高安全性地JavaScript

黑客攻击网站地主要手段有SQL注入,网络钓鱼,跨站攻击,拒绝服务攻击等。

常见的Web前端攻击方式

1.XSS

XSS是Cross Site Scripting的缩写,即跨站点脚本攻击。xss发生在用户的浏览器端,即当用户在加载HTML文档时执行了非预期的恶意脚本。

特点:尽一切办法在目标网站上执行非目标网站上原有的脚本

2.CSRF

CSRF是Cross Site Request Forgery的缩写,为跨站请求伪造。

3.界面操作劫持

界面操作劫持分为点击劫持和拖放劫持。利用在网页中内嵌一个透明的iframe来达到欺骗用户的目的。

不要轻易信任任何外部传入的数据

前端开发中应用的具体实践方法:

1.不要轻易信任用户输入的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZ7KxQ9E-1576226824856)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576137087508.png)]

2.不要轻易信任任何传入的第三方数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LYxqIJiC-1576226824857)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576137135802.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kA2ynfSr-1576226824858)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576138161316.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vz6e2z3D-1576226824859)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576138194063.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AwPrMrpz-1576226824859)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576138220337.png)]

3.不要仅仅靠JavaScript代码来阻止注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eyGjf3dH-1576226824860)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576138254248.png)]

其他前端安全防范实践

1.更安全地使用Cookie

在很多网站中,Cooike是用来持久化用户在网站中登录的。如果取得Cooike,就可以劫持用户在网站上的权限。导致信息泄露。

避免这种泄露的方式是设置Cooike为HttpOnly,禁止了JavaScript操作Cooike

另一个和安全相关的设置即,Secure。设置了Secure的Cooike只能在浏览器使用HTTPS请求时被发送到服务器端。

2.防止网页被其他网站内嵌为iframe

传统的方式是使用JavaScript代码来阻止网页被其他网页嵌套,首先在页面中添加如下的样式:

<style id="antiClickjack">
    body{display:none !important;}
style>

同时添加类似如下的JavaScript代码:

<script type="text/javascript">
    if (self === top){
        var antiClickjack = document.getElementById("antiClickjack");
        antiClickjack.parentNode.removeChild(antiClickjack);
    } else {
        top.location = self.location;
    }
script>

如上的代码首先设置了整个页面不可见,随后在JavaScript代码中检测页面是否被内嵌。如果没有被内嵌,则移除设置页面不可见的样式,否则把顶层页面的地址设置为内嵌页面的地址,从而阻止了页面的内嵌。

浏览器也支持通过设置X-Frame-Options响应头来控制页面被其他页面内嵌。

移动Web前端开发

移动web前端开发最佳实践

移动web前端开发概述

主流的移动终端和移动浏览器

智能移动终端主要以智能手机和平板电脑为主,智能系统主要以IOS和Android这两大系统。

Safari,Android,Chrome都是以WebKit为核心的浏览器。

移动端和桌面端Web前端开发的差异

在设计和开发移动端的网页时需要考虑以下这些具体的差异:

1.移动设备和PC之间的页面显示差异

智能手机屏幕比PC显示器要小,横向竖向滚动条,小屏幕中每行显示的字符数也很有限,可读性差。

IOS平台的Safari浏览器中定义了一个名为viewport的标签。这个viewport的作用是在浏览器中创建一个虚拟的窗口,而这个窗口默认的像素为980像素。

开发者可以自定义页面的viewport的宽度,高度,初始缩放,以及最大和最小缩放等属性,以适应设计的要求。如下代码:

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>

2.在移动设备和桌面端Web前端开发中,事件绑定存在差异

移动设备上可以做多触摸操作,在PC上主要是鼠标的单一点击操作。

3.页面控件设计上存在差异

PC端的用户习惯于使用鼠标操作,移动端的用户使用手指触摸操作

4.移动设备的网络带宽普遍比PC慢,移动端网页会设计的更简洁

如何让桌面web页面兼容移动设备

开发一个移动端网站兼容所有设备包括PC,各种尺寸的平板电脑及智能手机,网站设计需要遵循一定的原则,如下过程需要注意:

1.使用流式布局

为了让网页在浏览器中可以随着浏览器窗口的大小而自动适应,于是提出了一个流式布局。

流式布局和固定布局是相对的,流式布局的核心思想:使用百分比来设置各部分的宽度,而固定布局是:页面主要模块使用了固定的宽度。

流式布局优点:无论窗口有多大,网页中的各个模块都可以完整的展示在窗口中,不会因为浏览窗口变窄而导致页面部分模块隐藏。

2.借助与CSS Media queries(媒体查询)技术

Media queries是在CSS3中新加入的特性,通过指定媒体类型方式来限定所包含样式的作用范围,如下:

<link rel="stylesheet" media="(max-width:800px)" href="example.css"/>

<style>
    @media (max-width:600px){
        .facet_sidebar{
            display:none;
        }
    }
style>

代码中第一个示例是把css代码文件的作用域限制在了窗口尺寸800像素的范围内

第二个示例是把代码的作用域限制在了小于600像素的范围。

编写Media queries样式时,最好的做法是仅仅限定显示窗口的尺寸,而不是限定设备尺寸,分辨率等

按照尺寸从小到大编写不同的样式,比如:

/* 智能手机 <480px */
@media (max-width:480px){
}

/* 竖屏的平板 <768px */
@media (max-width:768px) and (min-width:480px){
}

/* 横屏的平板 >768px */
@media (max-width:1024px) and (min-width:768px){
}

/* 卓面PC >1024px */
@media (min-width:1024px){
}

3.使用合适的图片显示兼容方案

在网页中,图片是不可或缺的元素,有必要解决图片在移动设备的兼容性问题。一个简单而有效的做法是针对图片设置一个css样式,如下:

img {
    max-width:100%;
}

上述代码意思时让所有的图片最大宽度值为其容器的宽度。

4.保持页面简洁,不要使用移动设备不兼容的技术

不要再网页核心模块使用Flash技术。

5.设置viewport

<meta name=viewport content="width=device-width,initial-scale=1">

6.增加链接和按钮的可操作区域

相邻点击控件之间应该留有足够的空间,防止一次操作多个目标控件。推荐的间隔是至少32像素。

7.使用响应式设计框架

响应式设计包括了多种技术,如流式布局,图片兼容显示,Media queries等技术。

应用响应式设计时,经常遇到的难点是在小尺寸设备上无法适应设备屏幕的模块,而是按照模块的重要性来决定要隐藏的模块。

响应式框架Bootstrap。

8.使用工具检查网页的移动设备兼容性

推荐的工具有:MobiReady ,iPadPeek,Howtogomo

开发移动web站点的准备工作

在开发一个移动端之前需要考虑:

1.确定支持的移动设备

包括屏幕显示尺寸,DPI,内存及CPU性能,常用浏览器版本

2.处理和桌面端主网站的交互

3.设计移动站点为单页模式,避免页面的跳转

单页模式避免了页面跳转,加快了访问速度。

在移动站点的设计中,应该避免页面的跳转,除了规划页面整个的设计之外,还应该拦截所有页面中超链接的默认跳转方式,并修改为更友好的弹出层显示。

4.选择一个合适的移动前端框架

5.如何调试移动端页面

开发者可以在桌面端浏览桌面端浏览器,浏览器内核基本相同,开发者可以在桌面端浏览器中打开移动端站点,调试和测试页面。如Chrom浏览器自带的开发工具等等。

移动web前端开发相关技术最佳实践

HTML相关最佳实践

1.在页面head中添加必要的meta或link信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzT1M5lM-1576226824861)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\1576223031936.png)]

2.利用移动设备的便利性

在PC端网页中使用mailto链接,让用户点击并快速发邮件,示例:

<a href="tel:1-406-666-2345">1-406-666-2345a>
<a href="sms:1-406-666-2345">发信息a>

3.不要使用iframe,谨慎使用table标签

CSS相关最佳实践

1.尽量少用图片,并使用内联图片代替小图片

开发者把这些图标作为一中特殊的字体使用即可,仅仅通过设置字体的大小和颜色的方式就可以修改图标的样式。如下:展示使用Bootstrap设置一个搜索图标的情况:

<span class="glyphicon glyphicon-search">span>

除了考虑使用web fonts技术替换部分图片,也可以把一些小尺寸的图片转换为内联图片来展现,及把图片转为Base64格式,并借助Data URLs技术把图片内容直接写在css或者html文档中。原理是减少了加载图片的HTTP请求数量,加快页面展示速度。

在CSS中使用内联图片的例子:

li {
    background:
        url(data:image/gif;base64,ROXXXXXXXXXXXXXX)
        no-repate
        left center;
}

/* 在html中使用内联图片的例子 */
<span"star" src="data:image/gif;base64,ROxxxxxxx"/>

2.不要使用 :hover伪类设置悬停效果

如果为了体现元素处于激活状态,可以改用 :active伪类来进行相应的设置

3.设置合理的字体大小和行高

推荐设置的字体大小最小为16像素。

4.在不需要选中文字的区域禁用文字选中的功能

-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;

在移动版Safari中,长按一个超链接后弹出一个对话框,用以下代码禁用:

-webkit-touch-callout:none;
JavaScript相关最佳实践

1.使用移动平台中特有的事件处理

如鼠标单击,键盘输入等

利用orientationchange事件来切换横竖屏显示时的效果设置,或者在不推荐的屏幕显示模式中显示提示信息,让用户切换到最佳的模式。

2.谨慎使用标准对话框,避免弹出窗口

在移动web开发中,避免使用window.open打开新窗口

3.谨慎使用Timer

围,如下:

<link rel="stylesheet" media="(max-width:800px)" href="example.css"/>

<style>
    @media (max-width:600px){
        .facet_sidebar{
            display:none;
        }
    }
style>

代码中第一个示例是把css代码文件的作用域限制在了窗口尺寸800像素的范围内

第二个示例是把代码的作用域限制在了小于600像素的范围。

编写Media queries样式时,最好的做法是仅仅限定显示窗口的尺寸,而不是限定设备尺寸,分辨率等

按照尺寸从小到大编写不同的样式,比如:

/* 智能手机 <480px */
@media (max-width:480px){
}

/* 竖屏的平板 <768px */
@media (max-width:768px) and (min-width:480px){
}

/* 横屏的平板 >768px */
@media (max-width:1024px) and (min-width:768px){
}

/* 卓面PC >1024px */
@media (min-width:1024px){
}

3.使用合适的图片显示兼容方案

在网页中,图片是不可或缺的元素,有必要解决图片在移动设备的兼容性问题。一个简单而有效的做法是针对图片设置一个css样式,如下:

img {
    max-width:100%;
}

上述代码意思时让所有的图片最大宽度值为其容器的宽度。

4.保持页面简洁,不要使用移动设备不兼容的技术

不要再网页核心模块使用Flash技术。

5.设置viewport

<meta name=viewport content="width=device-width,initial-scale=1">

6.增加链接和按钮的可操作区域

相邻点击控件之间应该留有足够的空间,防止一次操作多个目标控件。推荐的间隔是至少32像素。

7.使用响应式设计框架

响应式设计包括了多种技术,如流式布局,图片兼容显示,Media queries等技术。

应用响应式设计时,经常遇到的难点是在小尺寸设备上无法适应设备屏幕的模块,而是按照模块的重要性来决定要隐藏的模块。

响应式框架Bootstrap。

8.使用工具检查网页的移动设备兼容性

推荐的工具有:MobiReady ,iPadPeek,Howtogomo

开发移动web站点的准备工作

在开发一个移动端之前需要考虑:

1.确定支持的移动设备

包括屏幕显示尺寸,DPI,内存及CPU性能,常用浏览器版本

2.处理和桌面端主网站的交互

3.设计移动站点为单页模式,避免页面的跳转

单页模式避免了页面跳转,加快了访问速度。

在移动站点的设计中,应该避免页面的跳转,除了规划页面整个的设计之外,还应该拦截所有页面中超链接的默认跳转方式,并修改为更友好的弹出层显示。

4.选择一个合适的移动前端框架

5.如何调试移动端页面

开发者可以在桌面端浏览桌面端浏览器,浏览器内核基本相同,开发者可以在桌面端浏览器中打开移动端站点,调试和测试页面。如Chrom浏览器自带的开发工具等等。

移动web前端开发相关技术最佳实践

HTML相关最佳实践

1.在页面head中添加必要的meta或link信息

[外链图片转存中…(img-HzT1M5lM-1576226824861)]

2.利用移动设备的便利性

在PC端网页中使用mailto链接,让用户点击并快速发邮件,示例:

<a href="tel:1-406-666-2345">1-406-666-2345a>
<a href="sms:1-406-666-2345">发信息a>

3.不要使用iframe,谨慎使用table标签

CSS相关最佳实践

1.尽量少用图片,并使用内联图片代替小图片

开发者把这些图标作为一中特殊的字体使用即可,仅仅通过设置字体的大小和颜色的方式就可以修改图标的样式。如下:展示使用Bootstrap设置一个搜索图标的情况:

<span class="glyphicon glyphicon-search">span>

除了考虑使用web fonts技术替换部分图片,也可以把一些小尺寸的图片转换为内联图片来展现,及把图片转为Base64格式,并借助Data URLs技术把图片内容直接写在css或者html文档中。原理是减少了加载图片的HTTP请求数量,加快页面展示速度。

在CSS中使用内联图片的例子:

li {
    background:
        url(data:image/gif;base64,ROXXXXXXXXXXXXXX)
        no-repate
        left center;
}

/* 在html中使用内联图片的例子 */
<span"star" src="data:image/gif;base64,ROxxxxxxx"/>

2.不要使用 :hover伪类设置悬停效果

如果为了体现元素处于激活状态,可以改用 :active伪类来进行相应的设置

3.设置合理的字体大小和行高

推荐设置的字体大小最小为16像素。

4.在不需要选中文字的区域禁用文字选中的功能

-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;

在移动版Safari中,长按一个超链接后弹出一个对话框,用以下代码禁用:

-webkit-touch-callout:none;
JavaScript相关最佳实践

1.使用移动平台中特有的事件处理

如鼠标单击,键盘输入等

利用orientationchange事件来切换横竖屏显示时的效果设置,或者在不推荐的屏幕显示模式中显示提示信息,让用户切换到最佳的模式。

2.谨慎使用标准对话框,避免弹出窗口

在移动web开发中,避免使用window.open打开新窗口

3.谨慎使用Timer

在移动web开发中,要避免使用Timer来完成需要准确控制时间的任务

你可能感兴趣的:(学习笔记)