JiM-W

keep Moving


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

less

发表于 2016-06-08 | 分类于 less

less程序化编译CSS

1 语法:定义变量,LESS 允许开发者自定义变量,变量可以在全局样式中使用,变量使得样式修改起来更加简单。

1
2
3
4
5
/*语法:@变量名: 值*/
@mainColor : red ;
div {
color:@mainColor ;
}

2 Mixin 混入:功能对用开发者来说并不陌生,很多动态语言都支持 Mixin(混入)特性,它是多重继承的一种实现,在 LESS 中,混入是指在一个 CLASS 中引入另外一个已经定义的 CLASS,就像在当前 CLASS 中增加一个属性一样。

  • 样式混入
1
2
3
4
5
6
7
8
9
10
.red {
color : red ;
}
.border {
border:2px solid #000 ;
}
.mixin-class {
.red();
.border();
}
  • 函数混入(变量必须要有默认值:如果后面的代码用到了该变量,否则会提示undefined)
1
2
3
4
5
6
7
8
9
10
.red(@color:red){
color : @color ;
}
.border(@color:#ccc,@width:3px){
border : @width solid @color ;
}
.mixin-func {
.red(skyblue);
.border(#666,10px);
}

3 嵌套:在我们书写标准 CSS 的时候,遇到多层的元素嵌套这种情况时,我们要么采用从外到内的选择器嵌套定义,要么采用给特定元素加 CLASS 或 ID 的方式”

比如以下这段html的嵌套书写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="container">
<div class="row">
<div class="column">
<h3></h3>
<a href=""><img src="" alt=""/></a>
</div>
<div class="column">
<h3></h3>
<a href=""><img src="" alt=""/></a>
</div>
<div class="column">
<h3></h3>
<a href=""><img src="" alt=""/></a>
</div>
</div>
</div>

css样式如下:

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
.container{
width:1000px;
height:80px;
position:relative;
}
.container>.row {
width:100%;
height:100%;
}
.container>.row>.column {
width:33.333%;
height:100%;
border:2px solid #000;
}
/*后代选择器*/
.container>.row>.column h3 {
margin:0;
}
.container>.row>.column a {
dispaly:block;
width:100%;
height:100%;
text-decoration:none;
}
.container>.row>.column a : hover {
color:#dddddd;
background-color:#ccc;
}

less编译如下(注意伪类需要加 &:伪类 )

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
.container {
width:1000px;
height:80px;
position:relative;
.row {
width:100%;
height:100%;
.column {
width:33.333%;
height:100%;
border:2px solid #000;
h3 {
margin:0;
}
a {
dispaly:block;
width:100%;
height:100%;
text-decoration:none;
}
/*&:伪类*/
&:hover {
color:#dddddd;
background-color:#ccc;
}
}
}
}

注意伪类选择符:E:hover E : link E :first-child

4 Import导入:可以使我们的样式编译模块化,这个思想很重呀,模块化的编程会使我们的维护特别简单。

1
@import "lessFileName";

5 Less cmd命令符

1
lessc -v :查看less文件的版本;

6 在less文件中,/**/ 注释同样可以在css中出现,而 // 注释只会在less中出现,不会再编译的css中出现。

div居中的几种方式

发表于 2016-06-02 | 分类于 css

div居中的几种方式

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
* 水平居中:给div设置一个宽度,然后添加margin:0 auto属性
div{
width:200px;
margin:0 auto;
}
* 让绝对定位的div居中
div {
position: absolute;
width: 300px;
height: 300px;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: pink; /* 方便看效果 */
}
* 水平垂直居中一
确定容器的宽高 宽500 高 300 的层
设置层的外边距
div {
position: relative; /* 相对定位或绝对定位均可 */
width:500px;
height:300px;
top: 50%;
left: 50%;
margin: -150px 0 0 -250px; /* 外边距为自身宽高的一半 */
background-color: pink; /* 方便看效果 */
}
* 水平垂直居中二
未知容器的宽高,利用 `transform` 属性
div {
position: absolute; /* 相对定位或绝对定位均可 */
width:500px;
height:300px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: pink; /* 方便看效果 */
}
* 水平垂直居中三
利用 flex 布局
实际使用时应考虑兼容性
.container {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.container div {
width: 100px;
height: 100px;
background-color: pink; /* 方便看效果 */
}

伪类选择符

发表于 2016-05-28 | 分类于 css

伪类选择符

一 先看定义:

​ E:first-child{ } :匹配父元素的第一个子元素E。

要使该属性生效,E元素必须是某个元素的子元素,E的父元素最高是body,即E可以是body的子元素

注意两点 第一 E 必须是某个元素的子元素 第二 E 必须是该元素的 第一个子元素,否则无法获取;

​ E:first-of-type{ } : 匹配同类型中的第一个同级兄弟元素E ,可以理解为在同辈元素中找到所有的E 元素组成一个新的集合,可以选中这个新的集合中的第一个E 元素

要使该属性生效,E元素必须是某个元素的子元素,E的父元素最高是html,即E可以是html的子元素,也就是说E可以是body
该选择符总是能命中父元素的第1个为E的子元素,不论第1个子元素是否为E

注意和first-child 的区别,第一:E 必须是某个元素的子元素,第二 E 不必是父元素的额第一个子元素

​ E:nth-child (n){ } :匹配父元素的第n个子元素E,假设该子元素不是E,则选择符无效。注意n 的取值是从 1 开始。

要使该属性生效,E元素必须是某个元素的子元素,E的父元素最高是body,即E可以是body的子元素
该选择符允许使用一个乘法因子(n)来作为换算方式,比如我们想选中所有的偶数子元素E,那么选择符可以写成:E:nth-child(2n)

注意:第一:E元素必须是某个元素的子元素,第二,n的取值要对应父元素的所有子元素组成的集合的索引值

​ E:nth-of-type(n) { } :匹配同类型中的第n个同级兄弟元素E。 可以理解为在同辈元素中找到所有的E 元素组成一个新的集合,可以选中这个新的集合中的第 n 个E 元素

要使该属性生效,E元素必须是某个元素的子元素,E的父元素最高是html,即E可以是html的子元素,也就是说E可以是body
该选择符总是能命中父元素的第n个为E的子元素,不论第n个子元素是否为E

二 :直接撸代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style>
p:first-child {
background-color: pink;
}
p:first-of-type {
color: blue;
}
</style>
<div>
<p>第1个p</p>
<p>第2个p</p>
<span>第1个span</span>
<p>第3个p</p>
<span>第2个span</span>
</div>

结果:第一个p 的背景色会变,颜色字体会变(注意:大家最可能搞混的是选中第一个p会这么写

1
div:first-child { } //这么写是错误的,大家注意区分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div>
<div>这是一个div </div>
<p>第1个p</p>
<p>第2个p</p>
<span>第1个span</span>
<p>第3个p</p>
<span>第2个span</span>
</div>
<style>
p:first-child {
background-color: pink;
}
p:first-of-type {
color: blue;
}
</style>

结果:第一个p的背景色不会变,颜色字体会变。

如果在前面加一个div,那么不会改变:

  • first-child伪类选择器选择的元素必须是某个父元素的的第一个子元素才能被选中。

  • first-of-type 伪类选择器选择的可以选择第一个该类型的元素,无论其是不是父元素的第一个子元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
p:nth-child(1){
font-size: 30px;
}
</style>
<div>
<p>第1个p</p>
<p>第2个p</p>
<span>第1个span</span>
<p>第3个p</p>
<span>第2个span</span>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
p:nth-child(1){
font-size: 30px;
}//这行代码已经无法命中第一个p,需要用下面的代码
p:nth-of-type(1){
font-size: 30px;
}
</style>
<div>
<div>这是一个div </div>
<p>第1个p</p>
<p>第2个p</p>
<span>第1个span</span>
<p>第3个p</p>
<span>第2个span</span>
</div>
  • nth-child(n) 伪类选择器,选择的范围是所有子元素的同辈元素组成的一个集合,然后n代表该集合中某个元素的索引 p:nth-child(2) 可以获取 ‘’第1个p’ p:nth-child(3) 可以获取 ‘第2个p ‘’;注意:如果里面是n的表达式

    比如p:nth-child(n) ,也是会选择中所有的p标签,n或从 0 一直递增。选择的过程是:判断第一个div,发现不是p标签,然后不选中,执行n+1,此时判断第一个p ,判断出来是一个p标签,然后选中,依次类推。

  • nth-of-type(n) 伪类选择器,选择的范围是所有子元素中该类型的元素组成的一个集合,然后 n 代表该类型结合中元素的索引 比如 p:nth-of-type(2){ } 则可以选中第2个p p:nth-of-type(3){ } 则可以选中第3个p

三 last-child last-of-type nth-last-child(n) nth-last-of-type(n),和上面一样,只是从后面开始

四 需要注意的一点就是 first-child last-child 。

五 综合下jquery

1
2
3
4
5
<script src=jquery-1.12.2.js> </script>
<script>
$("p:first-child").css("border","2px solid green");
$("p:first-of-type").css("border","2px solid red");
</script>

在jquery中也是如此,如果用first-child 伪类选择该元素,那么该元素必须是其父元素的第一个子元素,仔细回顾伪类的定义;first-of-child ,等以上的几个伪类选择器,在jquery中一样的规则。可以说新的CSS 3 向jquery学习和借鉴了很多特点。

二 关系选择符

  • E+F 只会选择所有匹配到的E后面紧邻 的F元素
  • E~F 只会选择所有匹配到的E后面所有 的F元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style>
p+p{
font-size: 30px;
}
//这行代码只能选中 第2个p 和 第4个p
p~p{
font-size: 30px;
}
//这行代码将选中 第2 3 4 5 个p
</style>
<div>
<div>这是一个div </div>
<p>第1个p</p>
<p>第2个p</p>
<span>第1个span</span>
<p>第3个p</p>
<p>第4个p</p>
<span>第2个span</span>
<p>第5个p</p>
</div>

margin auto position定位使盒子居中

发表于 2016-05-23 | 分类于 css html

position定位如何在父盒子居中

一 简单了解position定位取值:

  • position:left right bottom top length | %
  • length 是确定单位距离的取值,单位以px em等
  • 百分比%,此时要明确百分比对应的取值标准,水平方向 left= 百分比值 X 父元素的宽度(基准是父元素padding+width),垂直方向 top = 百分比值 X 父元素的高度(此时基准是父元素的padding+height);前提是父元素设置了除 static之外的定位,否则,百分比取值基准是浏览器的高度和宽度。

二 margin 取值

  • auto:水平(默认)书写模式下,margin-top/margin-bottom计算值为0,margin-left/margin-right取决于可用空间;这也是块级元素的流体特性 。思考 auto 的取值什么时候会起作用。
  • length : 用长度值来定义外补白。可以为负值
  • 百分比: 用百分比来定义外补白。水平(默认)书写模式下,参照其包含块 width 进行计算,其它情况参照 height ,可以为负值

三:理解margin的auto取值问题:

  • 标准流下的margin的auto取值:对于块级元素,margin: 0 auto ;可以使块级元素居中显示,就是利用了块级元素的流体特性
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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.bigbox {
width: 800px;
height: 200px;
margin: 100px auto;
//使bigbox在body中居中
border: 1px solid #000;
}
.smallbox {
width: 100px;
height: 100px;
background-color: limegreen;
margin:0 auto;
//使smallbox在bigbox中居中
}
</style>
</head>
<body>
<div class="bigbox">
<div class="smallbox"></div>
</div>
</body>
</html>
  • 标准流下的auto取值:如果发生了元素转化,块级元素转化为行内块元素,display:inline-block position float 等
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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.bigbox {
width: 800px;
height: 200px;
margin: 100px auto;
//使bigbox在body中居中
border: 1px solid #000;
position:absolute;
//display:inline-block;
}
.smallbox {
width: 100px;
height: 100px;
background-color: limegreen;
margin:0 auto;
//使smallbox在bigbox中居中
position:absolute;
//display:inline-block;
}
</style>
</head>
<body>
<div class="bigbox">
<div class="smallbox"></div>
</div>
</body>
</html>

建议大家拿到自己的浏览器上看效果:此时 margin的 auto 你会奇怪的发现不起作用了。

bigbox不在body中居中,smallbox不在bigbox中居中。

auto:水平(默认)书写模式下,margin-top/margin-bottom计算值为0,margin-left/margin-right取决于可用空间。品味这句话:我们可以理解,块级元素独占一整行,即使设置了宽高,仍然独占一整行;而行内块元素却不是。所以 ,margin 的auto值对于块级元素使用时候,会使其居中显示,而对于行内块元素使用的时候,却不会使其居中。

四:定位使盒子居中的方法:

两种方法:

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.bigbox {
width: 800px;
height: 200px;
margin: 100px auto;
border: 1px solid #000;
position: relative;
}
.smallbox {
width: 100px;
height: 100px;
background-color: limegreen;
position: absolute;
left: 50%;
/*定位的百分比 left=百分比*父元素的宽度*/
margin-left: -50px;
}
</style>
</head>
<body>
<div class="bigbox">
<div class="smallbox"></div>
</div>
</body>
</html>
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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.bigbox {
width: 800px;
height: 200px;
margin: 100px auto;
border: 1px solid #000;
position: relative;
}
.smallbox{
background-color: limegreen;
width: 100px;
height: 100px;
position: absolute;
left: 0;
right: 0;
margin:0 auto;
}
</style>
</head>
<body>
<div class="bigbox">
<div class="smallbox"></div>
</div>
</body>
</html>

其中第二种方法适用于不知道子元素的高宽的时候想要使子元素居中的效果。其实也是利用了流体特性,因为元素既要距离左边距0 又要距离右边距0 同时给该元素设置了margin:0 auto; 所以会用margin值填充左右的补白;

扩展:如果去掉bigbox的宽度设置,那么,无论浏览器的窗口如何变化,都可以使盒子居中,包括大盒子的body居中,小盒子在大盒子居中。

DOMContentLoaded

发表于 2016-05-13 | 分类于 DOM

1 DOMContentLoaded 和 onload事件

onload事件会在页面或者图像加载完成后立即发生。

DOMContentLoaded这个事件是从HTML中的onLoad的延伸而来的,当一个页面完成加载时,初始化脚本的方法是使用load事件,但这个类函数的缺点是仅在所有资源都完全加载后才被触发,这有时会导致比较严重的延迟,开发人员随后创建了一种自定义事件,domready,它在DOM加载之后及资源加载之前被触发。jQuery中的$(function(){})就是封装的这个方法

1.1 先来看下浏览器向服务器发送请求之后,请求到了HTML文档之后便开始解析,先生成DOM树 ,然后生成CSSDOM树,再由二者结合生成渲染树(RenderTree),有了所有的节点的样式,浏览器便可以genuine这些节点以及它们的样式确定它们的位置和大小,这就是layout阶段,之后浏览器会进行渲染,总结如下

DOM–>CSSOM–>RenderTree–>layout–>Paint

1.2 当然了这个时候我们还没有考虑到javascript;javascript会阻塞DOM的生成,也就是说当浏览器解析HTML的时候,如果遇到了script标签就会停止对HTML的解析,转而进行处理javascript脚本

  • 如果脚本是内联的,浏览器会先执行这段javascript代码
  • 如果脚本是外联的,浏览器会先加载脚本,然后执行
  • 因为javascript可以查询任意对象的样式,也就是说在CSSOM解析完毕之后,javascript才会被执行

处理完毕脚本之后会继续解析HTML文档

1.3 总结:

  • 当文档中没有javascript脚本的时候,浏览器解析玩文档便能触发DOMContentLoaded事件
  • 如果文档中包含脚本,则会阻塞文档的解析,同时脚本的执行需要等待CSSOM解析完毕才能执行
  • DOMContentLoaded事件的触发不需要等待图片等其他资源加载完成

2 异步脚本

2.1 我们知道同步脚本的解析对网页渲染有影响,如果我们想要页面尽快的显示,那我们可以使用异步脚本;HTML5中有两种执行异步脚本的方法:defer和async

2.2 看下二者的区别

2.2.1 script脚本,没有defer和async属性

1
<script src="***.js"></script>

当HTML文档解析的时候遇到javascript标签,会停止对文档的解析,进而加载javascript脚本,加载完毕之后立即执行

2.2.2 defer脚本

1
<script src="***.js" defer></script>

当HTML文档解析的时候遇见defer脚本,则会在后台加载脚本,文档的解析过程不会中断,

当文档解析结束之后,defer脚本执行;defer脚本的执行顺序与定义的时候的位置有关

  • defer属性只适用于外联脚本,如果script标签没有src属性,只是内联脚本,不要使用defer
  • 如果声明了多个defer脚本,则会按照顺序进行执行
  • defer脚本会在DOMContentLoaded和loaded事件触发之前执行
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
<!DOCTYPE html>
<html>
<head>
<title>defer & async</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<!-- adding a 'defer' attribute, by default, the value will be 'true' -->
<script type="text/javascript" src="js/1.js" defer></script>
<script type="text/javascript" src="js/2.js" defer></script>
<script type="text/javascript" defer>
console.log(3);
</script>
</head>
<body>
<div class="text">Hello World</div>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
console.log('dom content loaded, ready state:', this.readyState);
}, false);
window.addEventListener('load', function() {
console.log('window loaded, dom ready state:', document.readyState);
}, false);
</script>
</body>
</html>
1
2
//js/1.js
console.log("1");
1
2
//js/2.js
console.log("2");

输出如下

1
2
3
4
5
3
1
2
20defer.html:17 dom content loaded, ready state: interactive
20defer.html:21 window loaded, dom ready state: complete

2.2.3 async脚本

1
<script src="***.js" async></script>

当HTML文档解析的时候遇见async脚本,则会在后台加载脚本,文档的解析过程不会中断,

脚本加载完成之后,文档停止解析,async脚本执行;async脚本执行完毕之后,文档继续解析

  • 只适用于外联脚本,这一点和defer一致
  • 如果有多个声明了async的脚本,其下载和执行也是异步的,不能确保彼此的先后顺序
  • async会在load事件之前执行,但并不能确保与DOMContentLoaded的执行先后顺序

2.2.4 async脚本不考虑依赖,加载完毕之后马上会执行,这点对于不需要依赖的javascript脚本是非常合适的,但是对于需要依赖的javascript脚本而言,defer无疑是最合适的。

window

发表于 2016-05-13 | 分类于 DOM

1 window对象

1.1 Window 对象表示浏览器中打开的窗口。

如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。

1.2 innerHeight innerWidth 表示浏览器中 文档显示区 的高度和宽度,如果F12,调出控制台,那么会影响文档显示区的高度

1.3 outerHeight outerWidth

iframe标签

contentDocument 属性能够以 HTML 对象来返回 iframe 中的文档。

可以通过所有标准的 DOM 方法来处理被返回的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
<script type="text/javascript">
function getTextNode()
{
var x=document.getElementById("frame1").contentDocument;
alert(x.getElementsByTagName("h2")[0].childNodes[0].nodeValue);
}
</script>
</head>
<body>
<iframe src="frame_a.htm" id="frame1"></iframe>
<br /><br />
<input type="button" onclick="getTextNode()" value="Get text" />
</body>
</html>

2 window对象的属性

2.1 location属性:window对象的location属性指向Location对象.通过如下方式可以查看所有的locatio对象的属性和方法

1
2
3
for (var key in location){
console.log(key + "-->"+location[key]);
}
hash 设置或返回从井号 (#) 开始的 URL(锚)。
host 设置或返回主机名和当前 URL 的端口号。
hostname 设置或返回当前 URL 的主机名。
href 设置或返回完整的 URL。
pathname 设置或返回当前 URL 的路径部分。
port 设置或返回当前 URL 的端口号。
protocol 设置或返回当前 URL 的协议。
search 设置或返回从问号 (?) 开始的 URL(查询部分)。

2.2 history属性: window对象的history属性指向History对象

1
2
3
4
5
<input type="button" value="按钮" id="btn"/>
<script>
//如果HTML以id来为元素命名,并且Window对象没有此名字的属性,Window对象会赋予一个属性,它的名字是id值,指向HTML 元素;
console.log(window.btn);//<input type="button" value="按钮" id="btn"/>
</script>

清除浮动的方式

发表于 2016-04-28 | 分类于 html

清除浮动的方式:

第一:给父元素设置高度

第二:给父元素设置 overflow:hidden ,zoom:1 (zoom :1用来兼容IE6)触发BFC,父元素仍然会被设置了浮动的子元素的高度撑开(如果父元素没有设置高度的话)

第三:伪元素,在当前元素的前后添加伪元素,使该伪元素设置:clear:both;注意height必须设置为0 ,否则该元素回避实际高出若干像素;

1
2
3
4
5
6
7
clearfix::before,clearfix::after {
content:"";
display:block;
visibility:hidden;//伪元素不可见
line-height:0;
height:0 ;
}

Ajax 如何处理缓存

发表于 2016-04-17 | 分类于 http ajax

1.GET请求缓存处理,不想要缓存GET请求?

浏览器会缓存GET请求,不会缓存POST请求,因此解决为:

浏览器就会在本地硬盘上 查找 与该 URL 相关联的 Cookie 。如果该 Cookie 存在,浏览器就将它添加到 request header的Cookie字段中,与 http请求`一起发送到该站点

方法1:GET请求URL后加随机数,让服务器认为是不同的请求,如:”http://www.example.com/index.jsp?class=articele&page=5&t"+new Date().getTime();

或者 URL 参数后加上 “?ran=” + Math.random(); //当然这里参数 ran可以任意取了

方法2:在ajax发送请求前加上xmlHttpRequest.setRequestHeader(“If-modified-since”,”0”);

方法3:在ajax发送请求前加上xmlHttpRequest.setRequestHeader(“Cache-Control”,”no-cache”);

方法4:若为jQuery ajax, 设置ajax属性cache:false;(注意:cache属性对post没有用,对get才有用)或者

beforeSend :function(xmlHttp){
xmlHttp.setRequestHeader(“If-Modified-Since”,”0”);
xmlHttp.setRequestHeader(“Cache-Control”,”no-cache”);
},

方法5:在服务器端响应请求时加上response.setHeader(“Cache-Control”,”no-cache,must-revalidate”);

方法6:使用POST代替GET,浏览器不会对POST做缓存

注意:为什么cache属性对post没有用,对get才有用?

因为1.浏览器缓存url请求原理就是判断url是否相同,url相同则读取缓存,url不相同则读取服务器

2.使用GET方式提交url类似”http://www.example.com/index.jsp?class=articele&page=5“,而POST方式提交url类似http://www.example.com/index.jsp,参数是在请求 head里的,不在url上,请求参数url始终相同

3.jquery ajax GET方式提交: data: “t=” + new Date().getTime(), 或者 data:{“t”: new Date().getTime()}或者cash:false都是在请求后面加上不同的参数,cach:false会启动生成参数附加在url请求里,因此浏览器认为是不同的请求,就重新请求服务器

the performance optimization of the JS code

发表于 2016-04-17 | 分类于 http

Javascritp代码性能优化

1 代码性能测试 : 简单方法 根据运行前后的时间来判断

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
//先定义一个数组
var arr = [];
// console.log(Boolean(arr));
for(var i = 0,len = 10000 ;i < len ; i++){
arr.push(i);
}
//定义一个函数累加求和
var sum = 0 ;//全局的sum变量
function loopFor (arr){
for(var i = 0 ; i < arr.length ; i++){
sum += arr[i]
}
}
//定义一个递归方法删除数组,shift()函数删除数组第一个函数,并返回删除元素
function loopShift(arr) {
if (!!arr.length) {
sum += arr.shift();
arguments.callee(arr);
}
}
//定义一个测试性能的函数
function test (fn,param){
//记录开始执行函数的时间
var start = new Date().getTime();
//开始执行函数
fn(param);
//记录结束执行函数的时间
var end = new Date().getTime();
//输出执行结果
console.log("sum="+sum+";"+"执行时间是"+(end - start)+"ms");
}
//分贝执行,看下效果
// test(loopFor,arr); //我电脑上大概0~1 ms
test(loopShift,arr);//这个大概10ms
</script>
</body>
</html>

综合来看,递归这种方法还是十分消耗性能的

2 浏览器开发者工具提供性能分析

开发者工具—-profiles —-Record Javascript CPU Profile

3 javascript性能优化

async 设置或返回是否脚本一旦可用,就应异步执行。
charset 设置或返回脚本的 charset 属性值。
cross Origin 设置或返回脚本的 CORS 设置。
defer 设置或返回当页面完成解析后是否执行脚本。
src 设置或返回脚本的 src 属性值。
text 设置或返回属于脚本子节点的所有文本节点的内容。
type 设置或返回脚本的 type 属性值。

当浏览器解析页面的时候,遇到了javascript代码,无论该代码是在内嵌式文件中还是在外链式文件中,页面的加载和渲染都必须停止下来等待脚本执行完毕,因为脚本可能改变页面或者javascript的命名空间;

改善性能的方法:

3.1 为了不影响页面的渲染,尽量将script标签放在body的底部

3.2 每个script标签在加载的时候,都会阻塞页面渲染,所以减少页面包含的script标签数量有助于改善这一情况;包括减少内嵌式或者外链式的script标签;async 属性规定一旦脚本可用,则会异步执行。类似于告诉浏览器链接进来的脚本不糊生成文档内容,因此浏览器可以在下载脚本的时候继续解析和渲染文档;

注释:async 属性仅适用于外部脚本(只有在使用 src 属性时)。

注释:有多种执行外部脚本的方法:

  • 如果 async=”async”:脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)
  • 如果不使用 async 且 defer=”defer”:脚本将在页面完成解析时执行
  • 如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本

3.3 动态创建脚本

文档对象模型允许我们使用javascript动态创建HTML的几乎全部文档内容,script标签和页面中的其他元素一样,很容易被创建;

1
2
3
4
5
var script =document.createElement("script");
script.type = "text/javascript";
script.src = 'script1.js';
document.getElementsByTagName("head")[0].appendChild(script);
//getElementsByTagName获取到的是一个nodeList(一个伪数组)
1
2
3
4
5
6
7
8
var script =document.createElement("script");
script.type = "text/javascript";
script.onload = function(){
console.log("script is loaded");
}
script.src = 'script1.js';
document.getElementsByTagName("head")[0].appendChild(script);
//通过监听onload事件加载script脚本
1
2
3
4
5
6
7
8
9
10
11
12
//对于比较** 的IE有着另外一种实现方式 script有一个属性 readyState
var script = document.createElement("script");
script.type = "text/javascript";
script.onreadystatechange = function(){
if(script.readyState == 'loaded' || script.readyState == "complete"){
script.onreadystatechange = null;
console.log("script is loaded");
}
};
script.src = "script1.js";
//script的readyState的属性值随着外部下载文件的过程而改变;
//uninitialized loading loaded interactive complete

如果想要实现兼容,我们需要封装一个代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function loadScript (url,callback){
var script = document.createELement("script");
script.type = "text/javascript";
if(script.readyState ){ //表示是IE
script.onreadystatechange = function(){
if(script.readyState == 'loaded' || script.readyState == "complete"){
script.onreadystatechange = null;//不在使用的函数需要清除掉,减少对内存的占用
callback();
}
}
}else{
script.onload = function(){
callback();
}
}
script.src = url ;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript('script1.js',function(){
console.log("script1.js is loaded");
})

3.4 通过对XHR发送请求,加载javascript脚本

1
2
3
4
5
6
7
8
9
10
11
var xhr = new XMLHttpRequest();
xhr.open('get','script1.js','true');
xhr.onreadystatechange = function(){
if(xhr.status >=200 && xhr.status <300 || xhr.status == 304){
var script = document.createElement("script");
script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
};
//有个缺点就是javascript文件必须与页面同域,不能从CDN(Content Delivery Network)下载

4 内存管理

虽然javascript具有垃圾回收机制,但是为了让页面具有更好地性能,还是需要进行内存的优化;对于局部变量,在其执行完毕之后,会被自动清除(闭包除外),但是对于全局变量以及全局的函数,如果数据不再使用,最好通过设置为null的形式进行手动接触占用

Ajax(Asynchronous JavaScript and XML)

发表于 2016-04-17 | 分类于 http

一:Ajax(Asynchronous JavaScript and XML)

客户端:发送请求,确定请求方式以及处理请求的URL,发送给服务器——>>ajxa(javascript+XMLHttpRequset):作为媒介,xhr的open() send() 以及onreadystatechange()方法处理客户端和服务器之间的联系<<——服务器:处理请求,后台程序处理数据,返回给客户端;可以实现异步交互。

同步交互:客户端向服务器发送请求,客户端的页面进行响应,刷新页面

异步交互:客户端向服务器发送请求,客户端的页面进行响应,并不会刷新页面。

(这个是我们对于页面感官上感受)

从浏览器和服务器之间来理解同步和异步

同步:浏览器发送请求,等待服务器的响应,等服务器返回响应,然后浏览器继续执行

异步:浏览器通过javascript内置XMLHttpRequest对象向服务器发送请求,不等待服务器响应,浏览器继续执行代码,等服务器状态改变,onreadystatechange监听到改变,会执行回调函数;

Ajax 采用一种沙箱安全模型。因此,Ajax 代码(具体来说就是 XMLHttpRequest 对象)只能对所在的同一个域发送请求

我们需要检测并判断响应头的MIME类型后确定使用request.responseText或者request.responseXML

JS——Ajax

1 ajax的要点是XMLHttpRequset对象,根据不同浏览器兼容性,下面代码可以创建兼容性极强的XMLHttpRequset对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script type="text/javascript">
function GetXmlHttpObject()
{
var xmlHttp=null;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
</script>

2 XMLHttpRequest对象重要的属性

  • readystate存储着服务器相应状态的信息每当服务器响应状态改变的时候,onreadystatechange函数就会被执行
  • status由服务器返回的HTTP状态代码 200一切正常 404 NOT FOUND 403 Forbidden
  • statusText由服务器返回的HTTP状态描述,比如200 “OK” 404 “NOT FOUND”
  • 以上三个当响应不完成的时候,可以通过输出它们判断问题所在
1
2
3
4
5
6
7
8
9
10
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 ){ //代表服务器已经完全接受响应
if(xhr.status == 200 ){ //代表服务器响应状态OK
sone code
}else{
alert("status is "+xhr.status) ;
}
}
}
//以上代码可以用来检测状态码的问题

当readyState小于3的时候,status statusText 读取这些属性会导致一个异常。(注意S大写)

0 Uninitialized 初始化状态。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
1 Open open() 方法已调用,但是 send() 方法未调用。请求还没有被发送。
2 Sent send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。
3 Receiving 所有响应头部都已经接收到。响应体开始接收但未完成。
4 Loaded HTTP 响应已经完全接收。
  • onreadystatechange属性存有服务器响应的函数,readyState数字每次改变都会执行该函数;

    1
    xmlHttp.onreadystatechange = function(){ };
  • responseText 用来获取由服务器返回的数据,返回字符串形式 ;(json格式)或者如果还没有接收到数据的话,就是空字符串 。

  • responseXML 与 responseText 以字符串 返回 HTTP 响应不同,responseXML 以 XML 返回响应。

    1
    responseXML 属性返回 **XML 文档对象** ,可使用节点树的方法和属性来检查和解析该对象;这些从数据库中选取的数据将被转换为 XML 文档,然后我们将使用 DOM 来提取要显示的值。
  • 所谓的服务器返回的数据,其实就是echo 输出的内容(这个内容就是服务器端的响应体),如果响应体是XML格式的文本,则需要用responseXML,如果响应体是字符串格式的文本,则需要用responseText来获取响应的内容;

3 XMLHttpRequest对象的重要方法:如何将请求发送到服务器

3.1 open( type,url,async) type代表客户端向服务器发送数据的方式,url代表服务器处理客户端发送数据的程序,async代表是异步处理还是同步处理,默认是true,异步处理,false是同步处理;

open(HEAD,url,true) ,

3.2 setRequestHeader(‘Content-Type’,’application/x-www-form-urlencoded’);

getAllResponseHeaders()

1
2
使用open("post",url)的时候必须这样设置;表示相应返回的资源格式
get请求可以不设置;setRequestHeader() 方法指定了一个 HTTP 请求的头部,它应该包含在通过后续 send() 调用而发布的请求中。这个方法只有当 readyState 为 1 的时候才能调用,在调用了 open() 之后,但在调用 send() 之前。

3.3 send( string ),将请求发往服务器;send() 把 readyState 设置为 2,并触发 onreadystatechange 事件句柄。必须在open()方法之后才能调用 ; 注意:添加一个随机数,以防服务器使用缓存的文件

3.4 栗子解释:

  • get请求 请求发送给服务器的数据直接附在URL地址的后面
1
2
xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates&r="+Math.random(),true);
xmlhttp.send();
  • post请求 请求发送的数据在send(string) ;
1
2
3
xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates&r="+Math.random());
  • async 异步处理 (true) 同步处理(false)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//async = true ;需要规定响应处于 onreadystatechange 事件中的就绪状态时执行的函数:
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();
//async =false ; 规定必须在响应完成之后才能执行javascript,此时不需要编写onreadystatechange,javascript代码紧跟在send()之后便可以;
xmlhttp.open("GET","test1.txt",false);
xmlhttp.send();
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

4 XMLHttpRequest对象监听服务器变化 onreadystatechanges属性发生变化的时候,可以执行函数体;responseText和responseXML得到响应体。

5 XMLHttpRequest是javascript的一个内置对象,这个对象可以用来给后台服务器发送数据,同时接受后台返回来的数据,通过javascript动态的操作返回的数据,从而实现了交互的友好型,不会再反复的刷新页面。因为之前发送请求的时候,都是通过document对象发送请求,所以会刷新页面,后来直接用XHR发送请求,则不会再刷新页面了;

jQuery— Ajax

1 ajax方法里面封装了底层的XMLHttpRequest对象,建立了发送请求和响应请求的过程,并且在发送请求和得到响应这个过程中定义了一系列的函数的函数;

2 jQuery Ajax是一个十分强大的封装体,ajax所有的技术基本上都可以设置,一个$.ajax(url,settings)基本上可以处理大部分服务器和客户端的通信;

3 下面一步步来用栗子了解 jQuery-Ajax底层实现原理;(有关XMLHttpRequest对象的兼容上面以及解释过,此处不再做兼容)

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
34
35
36
37
38
39
40
41
42
43
44
45
46
obj = {"type":"GET","data":"data","URL":"url"}
var $ = {
ajax : function(obj){
var xhr = new XMLHttpRequest();
if(typeof obj.data === "object"){
//因为data有可能是一个对象,将data自动转化为字符串;
var str = this.params(obj.data);//将data转化为字符串,这个就是 jQuery底层发送到服务器的数据。将自动转换为请求字符串格式的原理;
obj.data= str ;
}
if(obj.type == "GET"){
obj.url = obj.url+"?"+obj.data;
obj.data = null ;
}
xhr.open(obj.type,obj.url,true);
if(obj.type =="POST"){
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
xhr.send(obj.data);
xhr.onreadystatechange = function(){ //每次readyState值变化的时候,都活触发这个onreadystatechange监听器,所以要设定一些条件,来限制函数体的执行,
if(xhr.readyState == 4){ //响应完成
if(xhr.status == 200) { //状态ok
var res = xhr.responseText ;//(如果返回是XML类型的数据,则用 xhr.responseXML接受)
var resObj = JSON.parse(res);//这个就是jQuery底层实现:当dataType设置为json的时候,返回的数据类型是javascript对象;
obj.sucess(resObj);
}else{
obj.reeor();
}else{
obj.complete();
}
}
};
},
params: function (obj) {
var str = "";
for (var key in obj) {
//console.log(key);
str += key + "=" + obj[key] + "&"
}
console.log(str);
str = str.substr(0, str.length - 1);
console.log(str);
return str;
}
}

4 用法 语法: $.ajax({ URL [settings] }) 传入键值对形式的设置和URL

1
2
3
4
$.ajax ({
url : "url" , //表示要访问的服务器后台地址
settings : //以下详细说明settings设置
})

settings 设置

  • dataType : 请求服务器返回的数据类型;

    “text”: 返回纯文本字符串

    “xml”: 返回 XML 文档,可用 jQuery 处理。

    “html”: 返回纯文本 HTML 信息;包含的script标签会在插入dom时执行。

    “script”: 返回纯文本 JavaScript 代码。不会自动缓存结果。除非设置了”cache”参数。’’’注意:’’’在远程请求时(不在同一个域下),所有POST请求都将转为GET请求。(因为将使用DOM的script标签来加载)

    “json”: 返回 JSON 数据 ,服务器返回javascript对象;即经过JSON.parse()解析成javascript对象

    “jsonp” : 如果跨域的话,这个时候就不是XMLHttpRequest对象发送请求了,而是script标签发送请求,服务器返回的script代码会直接执行

    表示可以进行跨域请求;使用这种类型的话,会创建一个查询字符串参数 callback=?

    ,这个参数会加在请求的URL后面。服务器端应当在JSON数据前加上回调函数名,以便完成一个有效的JSONP请求。如果要指定回调函数的参数名来取代默认的callback

    如果指定了text html javascript 则将返回字符串;如果指定了XML 则将返回XML格式的数据,可以用XML DOM 对象操作

    我们必须确保网页服务器报告的MIME类型与我们选择的dataType所匹配。比如说,如果我们将dataType设置为xml,则要求服务器返回xml类型的数据,服务器端就必须声明 text/xml 或者 application/xml 来获得一致的结果。

    1
    2
    3
    4
    5
    <?php
    $callback=$_GET['back'];
    $data='{"username":"zhangsanlisiwangwsu"}';
    echo $callback."(".$data.")";
    ?>

situation:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function getInfo(obj){
console.log(obj);
}
</script>
<script src="js/jquery-1.12.4.js"></script>
<script>
$.ajax({
url:"04jsonp.php?callback=getInfo",
type:"GET",
dataType:"jsonp",//如果没有这行代码,就是返回纯文本的javascript代码
//既支持跨域资源,也支持本地资源,服务器返回的以javascript代码直接执行
//{ username: "zhangsanlisiwangwsu" }
success:function(res){
console.log(res);
}
})
</script>
</head>
<body>
</body>
</html>
  • jsonp : 在一个jsonp请求中重写回调函数的名字。这个值用来替代在”callback=?”中的 callback
  • jsonpCallback : 为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $.ajax({
    url:'http://study.com/data.php',
    dataType : 'jsonp',
    jsonpCallback:"myCall",
    jsonp:"funcName",
    success:function(data){
    }
    })
    // ?funcName=myCall&_=1488624180015
    //如果不设置 jsonp和 jsonpCallback
    // ?callback=jQuery111103367937101396201_1488624279118&_=1488624279119
  • type : jQuery默认 GET 其他值 POST ,规定请求的方式;

  • async Boolean (默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。

  • cache : 默认为true ,缓存 ,dataType : jsonp script 的时候默认为false

  • data : 传递给服务器的数据 ,如果是对象,则自动转化为字符串;必须为key/value 格式,如果value值是数组,则将为相应 的key对应每个数组的值;如果是GET请求,需要将参数附在url之后 

    1
    2
    data:{ "name":"Jhon", "age":[13,14] },
    jQuery将解析成这样的字符串 : ?name=Jhon&age%5B%5D=13&age%5B%5D=14 传递给服务器;

    必须 为 data: { “name”:”Jhon”,”age”:14 } 这种格式,其他的都会报错;

    即使 是data: ‘ {“name”:”Jhon”,”age”:15} ‘ 这种形式,发送到服务器的数据有误;

    当以键值对的对象发送给后台数据的时候,可以被转化为JSON的数据格式,key值方便后台查询

  • processData : (默认: true) 默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型
    “application/x-www-form-urlencoded”。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。

    发送 XML 数据至服务器。设置 processData 选项为 false,防止自动转换数据格式。

  • jsonp : JSON with padding 底层实现原理其实就是动态的创建
1…151617…20
JiM-W

JiM-W

keep fighting!

195 日志
52 分类
90 标签
© 2017 JiM-W
由 Hexo 强力驱动
主题 - NexT.Pisces