0%

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
var  checkTools={       
/*判断是否为null和undefined*/
isNull:function(str){
//先判断是否undefined
return (typeof(str) == undefined || str == null || str.length ==0) ? false : true;
},
stringCheck : function(str){
if(this.isNull(str)){
var ruleStr=/^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
return ruleStr.test(str);
}else{
return false;
}
},
//验证手机号
phoneCheck : function(str){
if(this.isNull(str)){
var ruleStr=/^(13[0-9]|15[0-9]|17[0-9]|18[0-9]|14[57])[0-9]{8}$/;
return ruleStr.test(str);
}else{
return false;
}
},
//验证邮箱
emailCheck : function(str){
if(this.isNull(str)){
var ruleStr=/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/;
return ruleStr.test(str);
}else{
return false;
}
},
//验证字符长度(验证输入字符串长度)
strlenCheck : function(str,starNum,overNum){
if(this.isNull(str)){
var len = parseInt(str.replace(/[^\x00-\xff]/g, '__').length);
var tag = false;
if(len<overNum && len>starNum){
tag=true;
}
return tag;
}else{
return false;
}
},
/*去除空格*/
trimSpace : function(str){
if(this.isNull(str)){
var str=str.replace(/(^\s*)|(\s*$)/g,'');
return str;
}
}
}

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="box">
<input type="text" id="a">
<span id="b"></span>
</div>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj,"hello",{
get:function(){
console.log("get方法触发了")
},
set:function(val){
document.getElementById("a").value = val;
document.getElementById("b").innerHTML = val
}
})

document.getElementById("a").addEventListener('keyup',function(e){
obj.hello = e.target.value
});
</script>
</body>
</html>

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
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!DOCTYPE html>
<html>
<head>
<title>图片预加载之无序加载</title>
<meta charset="utf-8">
<style type="text/css">
*{padding: 0; margin:0;}
html,body{
height: 100%
}
a{text-decoration: none;}
.box{
text-align: :center;
}
.btn{
display: inline-block;
height: 30px;
line-height: 30px;
border: 1px solid #ccc;
background-color: #fff;
padding:0 10px;
margin-right: 50px;
color: #333;
}
.btn:hover{
background-color: #eee
}
.loading{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #eee;
text-align: center;
font-size: 30px;
}
.progress{
margin-top: 300px;
}
</style>
</head>
<body>
<div class="box">
<img id="img" src="http://i2.hoopchina.com.cn/user/308/15960308/13383588090.jpg" width="1200"></img>
<p>
<a href="javscript:;" class="btn" data-control='prev'>上一页</a>
<a href="javscript:;" class="btn" data-control='next'>下一页</a>
</p>

</div>
<div class="loading">
<div class="progress">
0%
</div>
</div>
<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
<script type="text/javascript" src="preload.js"></script>
<script type="text/javascript">
var imgs = [
'http://i2.hoopchina.com.cn/user/308/15960308/13383588090.jpg',
'http://img.dwstatic.com/ls/ls20170411_bg.jpg',
'http://img.article.pchome.net/00/44/23/20/pic_lib/wm/2.jpg',
'http://lcd.yesky.com/imagelist/2009/044/404q4y8g4m0p.jpg',
'http://pc.duowan.com/uploads/allimg/2009-11/16101540-6-4k952.jpg',
'http://lcd.yesky.com/imagelist/2009/044/cgro54wt2t2x.jpg'
]


//不用插件的写法
/*var index = 0;
var len = imgs.length;
var count = 0;
$progress = $('.progress')

$.each(imgs,function(i,src){
var imgObj = new Image();
imgObj.src = src;
//无论是否加载成功 都会继续循环,否则如果有一张加载不出来就没法进行了
//下面是加载图片的回调 让load页走完
$(imgObj).on('load error',function(){
//每完成一次count++
$progress.html(Math.round((count+1)/len * 100)+'%');
if(count >= len -1){
$('.loading').hide();
document.title = '1/'+len;
}
count++;
})

})

$('.btn').on('click',function(){
if($(this).data('control') === 'prev'){
//判断index 是否小于0 小于返回0 不小于返回index;Math.max返回较大的那个
index = Math.max(0,--index)
}
else
{
index = Math.min(++index,len-1)
}
document.title = (index+1)+'/'+len;
$("#img").attr('src',imgs[index])
})*/


//用插件的写法
var index = 0;
var len = imgs.length;
$progress = $('.progress')

$.PreLoad(imgs,{
all:"ordered",//有序加载
each:function(count){ //每一张加载完执行的函数
$progress.html(Math.round((count+1)/len * 100)+'%');
},
all:function(){ //所有图片加载完执行的函数
$('.loading').hide();
document.title = '1/'+len;
}
})
//如果用不用JQURY插件调用 preload.js需要删除外边的大闭包 后面注释掉挂载到$.extend的方法
/* $(function(){
new PreLoad(imgs,{
each:function(count){
$progress.html(Math.round((count+1)/len * 100)+'%');
},
all:function(){
$('.loading').hide();
document.title = '1/'+len;
}
})

})*/

/*//有序加載,加載完第一張然後第二張,類似于漫畫
var len = imgs.length,
count = 0;

orderLoad();

function orderLoad(){
var imgObj = new Image();
$(imgObj).on("load error",function(){
count++;
if(count >= len){
//所有图片加载完毕
}else
{
orderLoad();
}
})
imgObj.src = imgs[count]
}*/


$('.btn').on('click',function(){
if($(this).data('control') === 'prev'){
//判断index 是否小于0 小于返回0 不小于返回index;Math.max返回较大的那个
index = Math.max(0,--index)
}
else
{
index = Math.min(++index,len-1)
}
document.title = (index+1)+'/'+len;
$("#img").attr('src',imgs[index])
})
</script>
</body>
</html>

preload.js

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
69
70
71
72
73
74
75
76
77
78
//图片预加载
(function($){
function PreLoad(imgs,options){
//如果图片只有一张有可能是字符串传进来的
this.imgs = (typeof imgs === 'string') ? [imgs]:imgs;
this.opts = $.extend({},PreLoad.DEFAULTS,options)
//判断是无序加载还是有序加载
if(this.opts.order === "ordered"){
this.ordered()
}
else{
this._unoredered();
}


}
PreLoad.DEFAULTS = {
order:"unoredered", //默认是无序的
each:null, //每一张图片加载完毕后执行的方法
all:null //所有图片加载完毕后执行的方法
}
//无序加载图片方法
PreLoad.prototype._unoredered = function(){
var imgs = this.imgs;
var opts = this.opts;
var count = 0;
len = imgs.length;

$.each(imgs,function(i,src){
if(typeof src != "string") return ;
var imgObj = new Image();
imgObj.src = src;
//无论是否加载成功 都会继续循环,否则如果有一张加载不出来就没法进行了
//下面是加载图片的回调 让load页走完
$(imgObj).on('load error',function(){
opts.each && opts.each(count);

if(count >= len -1){
opts.all && opts.all();
}
count++;
})
})
}

PreLoad.prototype.ordered = function(){
var imgs = this.imgs;
var opts = this.opts;
var len = imgs.length;
var count = 0;
orderLoad();

function orderLoad(){
var imgObj = new Image();
$(imgObj).on("load error",function(){
opts.each && opts.each(count)

if(count >= len){
//所有图片加载完毕
opts.all && opts.all();
}else
{
orderLoad();
}
count++;
})
imgObj.src = imgs[count]
}
}

//转换成jquery插件写法
$.extend({
PreLoad:function(imgs,opts){
new PreLoad(imgs,opts)
}
})

})(jQuery)

express安装步骤

1
2
3
4
5
6
npm install -g express
npm install -g express-generator
//进入目录下,安装ejs模板
express -e .
//安装
npm install

//gulpfile.babel.js 不同于gulpfile.js 因为都是用es6写配置文件

1
2
3
4
5
6
7
npm install -g express
npm install -g express-generator
//进入目录下,安装ejs模板
express -e .
//安装
npm install

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
      *{padding:0; margin:0;}
ul li{list-style: none;}
body{font-size: 12px; background-color: #323232; padding:100px;}
.tab{width: 300px; }
.tab .tab-nav{
height: 30px;
}

.tab .tab-nav li{
float: left;
margin-right: 5px;
background-color: #767676;
border-radius: 3px 3px 0 0;
}

.tab .tab-nav li a{display: block; height: 30px;
padding: 0 20px; color: #fff; line-height: 30px;text-decoration:none;}

.tab .content-wrap{background-color: #fff; padding:5px; height: 200px; }

.tab .content-wrap .content-item{height: 200px; display: none;position: absolute;}

.tab .tab-nav li.actived{background-color: #fff;}
.tab .tab-nav li.actived a{color: #777}

.tab .content-wrap .current{display: block;}

JS

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
   ;(function($){

var Tab = function(tab){
var _this = this;
this.tab = tab;
// 默认配置参数;
this.config = {
"tabCls":".tab",
"triggerType":"mouseover", //click,mouseover
"effect":"default", //切换效果:default,fade
"invoke":0, //默认显示第几个TAB
"auto":false //tab是否自动切换,可以指定毫秒数
}

var config = $.extend(this.config, this.getConfig());


// console.log(this.config)

//保存tab标签列表,对应的内容列表
this.tabItems = $(config.tabCls).find(".tab-nav li");
this.tabContItems = $(config.tabCls).find(".content-wrap > div");

if(config.triggerType){
this.tabItems.on(config.triggerType,function(){
_this.invoke(this);
})
}

if(config.auto){
this.timer = null;
this.loop = 0;
this.autoPlay();

this.tabContItems.hover(function(){
window.clearInterval(_this.timer)
},function(){
_this.autoPlay();
})

}


};

Tab.prototype = {
//获取配置参数


getConfig:function(){
var config = this.tab;
//是否有配置参数
if(config && config!=""){
return config
}
else
{
return null
}
},

invoke:function(item){
var index = $(item).index();

$(item).addClass('actived').siblings().removeClass('actived');

var effect = this.config.effect;

if(effect === "default"){

this.tabContItems.eq(index).addClass('current').siblings().removeClass('current');
}

if(effect === "fade"){

this.tabContItems.eq(index).fadeIn().siblings().fadeOut()
}
//如果开启了定时播放,鼠标点击标签后 下次自动播放就应该接在点击的标签后边
if(this.config.auto){
this.loop = index;
}

},

autoPlay:function(){
var _this = this;
var tabLength = this.tabItems.size();
this.timer = setInterval(function(){
_this.loop++;
if(_this.loop >= tabLength){
_this.loop = 0;
}
_this.tabItems.eq(_this.loop).trigger(_this.config.triggerType)

},this.config.auto)
}


};



window.Tab = Tab;
})(jQuery)

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
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
    <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css.css">
</head>
<body>
<div class="tab tab1">
<ul class="tab-nav">
<li class="actived"><a href="#">新闻</a></li>
<li><a href="#">娱乐</a></li>
<li><a href="#">电影</a></li>
<li><a href="#">科技</a></li>
</ul>

<div class="content-wrap">
<div class="content-item current">1111</div>
<div class="content-item">2222</div>
<div class="content-item">3333</div>
<div class="content-item">4444</div>
</div>
</div>

<div class="tab tab2">
<ul class="tab-nav">
<li class="actived"><a href="#">新闻</a></li>
<li><a href="#">娱乐</a></li>
<li><a href="#">电影</a></li>
<li><a href="#">科技</a></li>
</ul>

<div class="content-wrap">
<div class="content-item current">aaa</div>
<div class="content-item">bbb</div>
<div class="content-item">ccc</div>
<div class="content-item">ddd</div>
</div>
</div>


<script src="jquery-1.9.0.min.js"></script>
<script src="tab.js"></script>
<script>
$(function(){
var tab1 = new Tab({
"tabCls":".tab1",
"triggerType":"click",
"effect":"fade",
"invoke":2, //默认显示第几个TAB
"auto":1000
});

var tab1 = new Tab({
"tabCls":".tab2",
"triggerType":"click",
"effect":"default",
"invoke":1, //默认显示第几个TAB
"auto":false
});


})
</script>
</body>
</html>

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
   * {
margin: 0;
padding: 0
}

.switch {
width: 50px;
margin-top: 3px;
height: 22px;
background: #4f7cfe;
cursor: pointer;
border-radius: 11px;
position: relative;
transition: all .1s linear;
}

.switch em {
position: absolute;
left: 5px;
top: 0;
line-height: 22px;
width: 25px;
color: #fff;
font-style: normal;
font-size: 12px;
transition: all .1s linear;
}

.switch i {
position: absolute;
left: 29px;
top: 1px;
background: #fff;
width: 20px;
height: 20px;
display: block;
border-radius: 10px;
transition: all .1s linear;
}

.switch.switchOn {
background: #ccc;
}

.switch.switchOn em {
left: 23px;
}

.switch.switchOn i {
left: 1px;
}

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="switch"><em>ON</em><i></i></div>
<script>
$(".switch").click(function() {
if ($(this).hasClass("switchOn")) {
$(this).removeClass("switchOn");
$(this).find("em").text("ON");
} else {
$(this).addClass("switchOn");
$(this).find("em").text("OFF");

}
})
</script>

====================================

1
2
3
4
5
6
7
8
9
10
11
12
13
  $(".navbar-item").on("click", "li > a", function(){
// 激活态
$(".navbar-item ul a").removeClass("active");
$(this).addClass("active");

var href = $(this).attr("href");
if (href.substring(href.length - 1) != "#") {
var pos = $(href).offset().top;
$("html,body").animate({scrollTop: pos}, 300);
return false;
}
});

gulpfile.js的配置

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// 导入工具包 require('node_modules里对应模块')
var gulp = require('gulp'); // 本地安装gulp所用到的地方
var fileinclude = require('gulp-file-include'); // 包含HTML
var connect = require('gulp-connect'); // 本地服务
var imagemin = require('gulp-imagemin'); // 图片压缩
var watch = require('gulp-watch'); // 监听
var less = require('gulp-less'); // 编译less
var sass = require('gulp-sass'); // 编译sass
var notify = require('gulp-notify'); // 处理LESS错误
var plumber = require('gulp-plumber'); // 构建异常捕获,防止构建进程崩掉
var postcss = require('gulp-postcss'); // css 兼容
var autoprefixer = require('autoprefixer'); // 处理浏览器私有前缀
var cssnext = require('cssnext'); // 使用CSS未来的语法
var precss = require('precss'); // 像Sass的函数
var spritesmith = require('gulp.spritesmith'); // 精灵图片
var browserSync = require('browser-sync');
var reload = browserSync.reload;
var cssbeautify = require('gulp-cssbeautify'); // css 美化
var minifycss = require('gulp-minify-css'); // 压缩css
var concat = require('gulp-concat'); // 合并文件
var babel = require('gulp-babel'); // 将ES6代码编译成ES5
var uglify = require('gulp-uglify'); // 压缩js
var rename = require('gulp-rename'); // 重命名文件
var cached = require('gulp-cached'); // 文件缓存进内存
var remember = require('gulp-remember'); // 读取内存中的文件
var changed = require('gulp-changed'); // 比较文件改变
var gutil = require('gulp-util'); // 让电脑 哔 ~ 的响一声然后抛出异常
var debug = require('gulp-debug');

//include html并刷新服务器
gulp.task('fileinclude', function(done) {
gulp.src(['src/html/*.html'])
// .pipe(cached('fileinclude'))
// .pipe(remember('fileinclude'))
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(gulp.dest('dist/html'))
.on('end', done)
.pipe(reload({ stream: true }));
});

// 创建精灵图
gulp.task('sprite', function() {
var spriteData = gulp.src('src/images/sprite/*.png').pipe(spritesmith({
imgName: 'sprite.png',
cssName: '1_sprite.css',
cssFormat: 'css',
imgPath: '../images/sprite.png'
}));
spriteData.img.pipe(gulp.dest('src/images')); // output path for the sprite
spriteData.css.pipe(gulp.dest('src/css/css')); // output path for the CSS
});

// 压缩图片
gulp.task('imagemin', ['sprite'], function() {
var stream = gulp.src('src/images/*.+(png|jpg|jpeg|gif|svg)')
// 如果想对变动过的文件进行压缩,则使用下面一句代码
.pipe(cached(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(debug({ title: '图片文件————:' }))
.pipe(gulp.dest('dist/images'))
.pipe(reload({ stream: true }));
return stream;
});

// 打包CSS进入到dist目录
gulp.task('csstodist', ['testCSS', 'testLess', 'testSass', 'sprite'], function() {
var processors = [autoprefixer, cssnext, precss];
var stream = gulp.src('src/css/css/*.css')
.pipe(cached('csstodist'))
.pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
.pipe(postcss(processors))
.pipe(remember('csstodist'))
.pipe(debug({ title: '编译文件————:' }))
.pipe(concat('common.css'))
.pipe(cssbeautify({
indent: ' ',
openbrace: 'end-of-line',
autosemicolon: true
}))
// .pipe(rename({suffix: '.min'}))
// .pipe(minifycss())
.pipe(gulp.dest('dist/css'))
.pipe(reload({ stream: true }));
return stream;
});

// css 打包进入 src 文件夹
gulp.task('testCSS', function(callback) {
gulp.src('src/css/*.css')
// .pipe(cached('testLess'))
.pipe(changed('src/css/css'))
.pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
// .pipe(gulp.dest('src/css/css'))
.pipe(reload({ stream: true }));
callback();
});

// less 翻译 并 打包进入 src 文件
gulp.task('testLess', function(callback) {
gulp.src('src/css/*.less')
// .pipe(cached('testLess'))
.pipe(changed('src/css/css', { extension: '.css' }))
.pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
.pipe(less())
.pipe(gulp.dest('src/css/css'))
// .pipe(reload({ stream: true }));
callback();
});

// sass 翻译 并 打包进入 src 文件
gulp.task('testSass', function(callback) {
gulp.src('src/css/*.scss')
.pipe(changed('src/css/css', { extension: '.css' }))
.pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
// .pipe(sass().on('error', sass.logError))
.pipe(sass())
.pipe(debug({ title: '编译文件————:' }))
.pipe(gulp.dest('src/css/css'))
// .pipe(reload({ stream: true }));
callback();
});

// 打包Lib进入到dist目录
gulp.task('Libtodist', function() {
gulp.src('src/Lib/**/*')
.pipe(cached('Libtodist'))
.pipe(debug({ title: 'LIB复制文件————:' }))
.pipe(gulp.dest('dist/Lib'))
.pipe(reload({ stream: true }));
});

// 打包JS到dist目录
gulp.task('jstodist', function() {
gulp.src('src/js/**/*.js')
.pipe(plumber({
errHandler: function(e) {
gutil.beep(); // 哔~ 的响一声
gutil.log(e); // 抛出异常
}
}))
.pipe(changed('dist/js', { hasChanged: changed.compareSha1Digest }))
// .pipe(babel({ presets: ['es2015'] }))
.pipe(debug({ title: '编译文件————:' }))
// .pipe(remember('jstodist'))
// .pipe(concat('public.js'))
// .pipe(rename({suffix: '.min'}))
// .pipe(uglify())
.pipe(gulp.dest('dist/js'))
.pipe(reload({ stream: true }));
});

// 监视文件改动并重新载入
gulp.task('serve', function() {
browserSync({
port: 406,
server: {
baseDir: 'dist/'
}
});
});

// 监听所有HTML JS CSS改动
gulp.task('watch', function() {
gulp.watch(['src/css/*.css'], ['testCSS']);
gulp.watch(['src/css/*.less'], ['testLess']);
gulp.watch(['src/css/*.scss'], ['testSass']);
gulp.watch(['src/css/css/*.css'], ['csstodist']);
gulp.watch(['src/images/sprite/*'], ['sprite']);
gulp.watch(['src/Lib/**/*'], ['Libtodist']);
gulp.watch(['src/js/*.js'], ['jstodist']);
gulp.watch(['src/html/**/*.html'], ['fileinclude']);
gulp.watch(['src/images/*'], ['imagemin']);
});

gulp.task('default', ['csstodist', 'fileinclude', 'serve', 'imagemin', 'Libtodist', 'jstodist', 'watch']);



package.json的配置

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
{
"name": "njga",
"version": "1.0.0",
"description": "test",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^6.7.6",
"babel-core": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"browser-sync": "^2.17.3",
"cssnext": "^1.8.4",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-cached": "^1.1.1",
"gulp-changed": "^2.0.0",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.0.0",
"gulp-cssbeautify": "^0.1.3",
"gulp-debug": "^3.1.0",
"gulp-file-include": "^1.0.0",
"gulp-imagemin": "^3.0.3",
"gulp-less": "^3.1.0",
"gulp-minify-css": "^1.2.4",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^6.3.0",
"gulp-remember": "^0.3.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "^3.1.0",
"gulp-uglify": "^2.0.1",
"gulp-util": "^3.0.8",
"gulp-watch": "^4.3.10",
"gulp.spritesmith": "^6.3.0",
"precss": "^1.4.0"
}
}



安全类

1.CSRF 攻击
引诱用户点击链接登录到目标网站
防范措施:加 token 验证 , 第一次登录的时候存 token,refer 验证:看来源是不是本网站的,不是一律拦截

2.XSS 攻击

  • 一个博客网站,我发表了一篇博客,其中嵌入 script 脚本
    脚本内容:获取 cookie,发送到我的服务器(服务器配合跨域)
    发布这篇博客,有人查看他,可以轻松收割访问者的 cookie

注入脚本
防范措施:对一些表单输入的参数进行过滤限制

重排重绘

重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘

重排:页面上的盒模型都有自己的样式,浏览器会把他放在他该出现的位置
导致重排:改动 dom,display:none,加动画,resize 窗口等

减少重排重会:

避免使用 table 布局。
尽可能在 DOM 树的最末端改变 class。

避免使用 CSS 表达式(例如:calc())

避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。

可以使用 absolute 脱离文档流。

防抖和节流

  • 防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;多应用于 用户输入,防止频繁触发 change 事件
  • 函数在一段时间内的多次调用,仅使得最后一次调用有效
1
2
3
4
5
6
7
8
9
10
11
// 防抖
function debounce(func, delay) {
var timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(()=>{
func.apply(this, arguments);
}, delay);
}
}

  • 节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。多应用于 拖拽元素 获取位置
  • 函数在一段时间内的多次调用,仅第一次有效。
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
function throttle(func, delay) {
var timer = null;
return function () {
if (!timer) {
func.apply(this, arguments);
timer = setTimeout(() => {
timer = null;
}, delay);
} else {
console.log("上一个定时器尚未完成");
}
}
}


//时间戳版
function throttle(func, delay) {
var last = 0;
return function () {
var now = Date.now();
if (now >= delay + last) {
func.apply(this, arguments);
last = now;
} else {
console.log("距离上次调用的时间差不满足要求哦");
}
}
}

  • 为什么用闭包写防抖和节流? 因为避免 timer 全局污染

JS 运行机制

js 是单线程,异步任务先挂起,同步任务处理完毕再处理异步任务

1
2
3
4
5
6
console.log(1)
setTimeout(funciton(){
console.log(2)
},0)
console.log(3) //1 3 2

1
2
3
4
5
6
7
console.log('a')

while(true){

}

console.log('b') //a 同步任务 while一直在循环 执行不到B
1
2
3
4
5
6
for(var i=0; i<4; i++){
setTimeout(function(){
console.log(i) // 4 4 4 4 循环是同步的每次执行都将异步挂起,都循环完i =4 这个时候才把挂起的4次异步任务加入
},0)
}

同步>promise>promise.then>setTimeout

1
2
3
4
5
6
7
8
9
10
11
12

setTimeout(function () {
console.log(1)
}, 0);
new Promise((resolve) =>{
console.log(4)
resolve();
}).then(function () {
console.log(2);
});
console.log(3) //4,3,2,1

JS 垃圾回收机制

基本类型是:Undefined/Null/Boolean/Number/String

基本类型的值存在内存中,被保存在栈内存中。从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本。

引用类型:object

引用类型的值是对象,保存在堆内存中。

基本类型保存在栈中引用的内存地址不会改变,引用类型的保存在堆区内存可以改变

1
2
3
4
5
6
7
var a = 2;
var b = a;
b = 3

console.log(a) //2
console.log(b) //3

var b = a 这里 b 和 a 是独立的,因为 a 是值类型

1
2
3
4
5
6
var a = [1,2,3]
var b = a
b.push(4)
console.log(a) //[1,2,3,4]
console.log(b) //[1,2,3,4]

a 存放在栈 【1,2,3】在堆 栈区保存的变量指向堆区 var b = a 实际上 让 b 也指向这个堆区 ,所以就都改变了

JS 中最常见的垃圾回收方式是 1.标记清除。 2.引用计数

标记清楚:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

引用计数(低版本 IE 内存泄漏)1. 声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是 1。 3. 当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减 1.当垃圾收集器下一次运行时,它就会释放引用次数是 0 的值所占的内存

引起内存泄漏的原因:

1.变量相互引用

1
2
3
4
5
6
7
function problem() {
var objA = new Object();
var objB = new Object();

objA.someOtherObject = objB;
objB.anotherObject = objA;
}

这里存在循环引用会引起内存泄漏,引起内存泄漏解决方法

1
2
objA.someOtherObject = null
objB.anotherObject = null

2.意外的全局变量引起的内存泄漏。
全局变量,不会被回收,使用严格模式避免

3.闭包引起的内存泄漏

原因:闭包可以维持函数内局部变量,使其得不到释放。
解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对 dom 的引用。

闭包

1,可以访问外部函数作用域中变量的函数
2,被内部函数访问的外部函数的变量可以保存在外部函数作用域内而不被回收

实现累加

1
2
3
4
5
6
7
8
9
10
11
var a = (function(){
var s = 0;
return function (){
s++;
console.log(s)
}
})()

a()//1
a()//2
a()//3
1
2
3
4
5
6
7
8
9
10
11
var oli = document.getElementsByTagName('li');
var i;
for(i = 0;i < 5;i++){
oli[i].onclick = (function(num){
var a = num; // 为了说明问题
return function(){
alert(a);
}
})(i)
}
console.log(i); // 5

经典问题

1
2
3
4
5
6
7
8
for(var i=0; i<5;i++){
listArr[i].onclick = (function(n){
return function() {
console.log(n)
}
})(i)
}

1.为什么不写闭包就输出 5
因为 js 是单线程的 循环是同步,先执行, onclick 指向的匿名函数需要 onclick 才执行所以是异步,后执行,var 没有块级作用域,所以循环到 5 后 window.i ==5 因此,这时你点击任何一个 li,都要 alert(i); 局部作用域内没有声明 i 变量,因此会追溯到全局作用域的 i,所以弹出的都是 5。可以用 let 解决

2.为什么写闭包就正确了
循环的时候 已经将 listArr[i] 这里的 i 变成 0,1,2,3,4 ,click 时候 function 内找 n 没有,找向上层定义时的作用域,里面形参 n 是 for 时候赋值的当时的 i 值。

提升页面性能的方法

1.资源的压缩合并,减少 HTTP 请求

2.异步加载:动态脚本加载,defer(html 加载完后,逐一按顺序加载) async(无序的)

3.浏览器缓存 配置 Expires 头,设置过期时间 缺点:要求客户端时间和服务端严格一致,经常发送请求检查
cache-control 使用 max-age 指令指定组建被缓存多久,它以秒为单位定义一个更新窗。如果从组件被请求开始过去的秒数少于 max-age,浏览器就使用缓存的版本,这就避免了额外的 http 请求。

4.使用 cdn

5.DNS 预解析

****

从输入 URL 到页面加载发生了什么

DNS 解析
TCP 连接
发送 HTTP 请求
服务器处理请求并返回 HTTP 报文
浏览器解析渲染页面
连接结束

安装步骤

1
2
3
4
5
1.npm init

2.进入目录 npm install webpack --save-dev

npm install webpack -g

注意事项

1.读取css需要loader
npm install css-loader style-loader –save-dev

在入口的JS文件引入
require(‘style-loader!css-loader!./style.css’)

2.一些参数

webpack hello.js hello.bundle.js –watch –progress –display-modules –display-reasons

使用webpack.config.js配置

改写package.json –config webpack.config.js webpack.config.js改名了也用这个

1
2
3
4
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"webpack":"webpack --config webpack.config.js --watch --progress --display-modules --display-reason --colors"
},

npm run webpack 运行

html-webpack-plugin

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
69
70
71
72
73
74
75
76
npm install html-webpack-plugin --save-dev
var htmlWebpackPlugin = require('html-webpack-plugin')


module.exports={
//单入口
// entry:'./src/script/main.js',
//多入口
//entry:['./src/script/main.js','./src/script/a.js'],
//穿一个对象,假设有3个页面a,b,c 每个页面都引入main.js 每个页面都有单独的JS a,b,c
entry:{
main:'./src/script/main.js',
a:'./src/script/a.js',
b:'./src/script/b.js',
c:'./src/script/c.js',

},
output:{
//注意路径 这里只配到dist根目录下 在filename中才指定js/
path:'./dist',
//如果entry 是一个对象,有多个键值对(chunk), filename就不能写死一个名字
//其中hash是每次打包的哈希值,chunkhash 是每次打包都不同的哈希值 相当于md5
filename:'js/[name]-[chunkhash].js',

//打包上线后,替换路径为以下路径开头
// publicPath:'http://cdn.com'
},
plugins: [
//html-webpack-plugin 这个插件可以把打包生成js自动引入到页面中,因为打包生成的名字带有
//哈希值,每次都不同
new htmlWebpackPlugin({
//模板参照根目录下的index.html,这样根目录的index.
//html里的内容也会被搬进这个插件生成的index.html
template: 'index.html',
//指定带有hash值的名称 index-[hash].html,每次都生成不同的INDEX.HTML
filename:'a.html',
//可将JS直接插入到头部,不写就是尾部
// inject:'head',
//设置false 手动在 头尾自定义script引入位置
inject:'body',
//可在index.html中通过<%= htmlWebpackPlugin.options.title %>
title:'this is a',
//任何属性都可以被通过ejs模板方式引入到页面
//date:new Date(),
//仅引入和自己页面相关的chunks
chunks:['main','a']

//压缩output
/* minify:{
//删除注释,空格
removeComments:true,
collapseWhitespace:true

}*/

}) ,

new htmlWebpackPlugin({
template: 'index.html',
filename:'b.html',
inject:'body',
title:'this is b',
//date:new Date(),
chunks:['main','b']
}) ,

new htmlWebpackPlugin({
template: 'index.html',
filename:'c.html',
inject:'body',
title:'this is c',
//date:new Date(),
chunks:['c']
})
]
}

loader

1.安装babel loader(es6 转 es5)
npm install –save-dev babel-loader babel-core

2,安装preset latest

npm install –save-dev babel-preset-latest

建立.babelrc 内容
{
“presets”:[“latest”]
}

3.安装css-loaer postcss
npm install css-loader style-loader –save-dev
npm install postcss-loader –save-dev
npm install autoprefixer –save-dev

可以查看npm官网 postcss用法
webpack.config.js
{
test: /.css$/,
loader:’style-loader!css-loader!postcss-loader’
}

根目录下建立postcss.config.js

module.exports = {
plugins: [
require(‘autoprefixer’)({
browsers:[‘last 5 versions’]
})
]
}

4,安装less-loader
$ npm install -g less
npm install less-loader –save-dev

5.安装html-loader

npm install html-loader –save-dev

6,处理图片

npm install file-loader –save-dev

npm install url-loader –save-dev
//处理图片可以用file-loader ,也可以用url-loader
//limit 限制图片大小 200000代表200K 我插入的图片是109K
//如果小于这个200K ,则插入BASE64编码,大于还是插入图片

压缩图片

npm install image-webpack-loader –save-dev