Javascript

基础

好用方法

  1. 二维数组横纵列转置的方法
1
2
3
4
5
var newArray = arr[0].map(function(col, i) {
return arr.map(function(row) {
return row[i];
})
});

插件、工具等

form

1. 使用

form简单赋值
1
2
3
4
var edit = $('#editForm');
for (var p in data) {
edit.find(":input[name='" + p + "']").val(data[p]);
}
form清空
1
document.getElementById("editForm").reset();

EJS

1. Node.js后台渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="main-content">
<!--left-fixed -navigation-->
<% include ./layout/sidebar.html %>
<!--left-fixed -navigation-->
<!-- header-starts -->
<% include ./layout/header.html %>
<!-- //header-ends -->
<% var page ="./page/"+pagename+".html"%>//定义一个变量,用来动态引入
<%- include(page)%>
<!-- footer-starts -->
<% include ./layout/footer.html %>
<!-- //footer-ends -->
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var ejs = require('ejs');
var express = require('express');
path = require('path')

var app = express();

app.engine('html', ejs.__express);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

exports.login = async function(req, res) {
try{
var user = req.session.user;
if (!user) {
res.render('login', {});
} else {
res.redirect('/');
}
}catch (exp){
log.error('controller login error:' + exp);
res.render('login', {});
}
};
渲染后返回HTML字符串
1
2
3
4
var listStr = fs.readFileSync(__dirname+"/../views/page/"+fname+"/"+fname+"L.html","utf8")
var listHtml = ejs.render(listStr, {list: result.list});
var pageStr = fs.readFileSync(__dirname+"/../views/page/page.html","utf8")
var pageHtml = ejs.render(pageStr, {data: result.data});
HTML替换
1
$("#downPage").html(data.pageHtml);

Bootstrap Modal-dialog

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
48
49
50
51
52
53
54
55
56
57
<script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>

<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-hidden="true" style="display: none;">
<div class="modal-dialog" role="document">
<div class="modal-content modal-info">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form id="editForm" action="mail" method="post">
<input id="id" name="id" hidden>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>类别</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="rewardType" name="rewardType" type="text">
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>日期</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="date" name="date" class="form_date" type="text" required readonly>
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>描述</h5>
</div>
<div class="col-md-9 grid-form1">
<textarea id="content" name="content"></textarea>
</div>
<div class="clearfix"></div>
</div>
<div class="bottom-form">
<div class="col-md-9 grid-form1">
<button type="submit" class="btn btn-sm btn-primary" id="editSubmit">保存</button>
<button type="reset" class="btn btn-sm btn-default" data-dismiss="modal">关闭</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>
</div>
</div>
</div>

<!-- 打开 -->
<a href="#" style="line-height: 0.5em;" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#editModal" onclick="editShow(<%= i %>)">编辑</a>
<!-- 关闭 -->
$('#editModal').modal('hide');

BootstrapValidator

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
<script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>
<link href="css/bootstrapValidator.css" rel="stylesheet">
<script src="js/bootstrapValidator.js"></script>

<input id="id" name="id" type="number" required>

//移除上次的校验配置
if($("#editForm").data('bootstrapValidator')) {
$("#editForm").data('bootstrapValidator').destroy();
$('#editForm').data('bootstrapValidator', null);
}

$('#editForm')
.bootstrapValidator()
.on('success.form.bv', function(e) {
e.preventDefault();
var $form = $(e.target);
//是否通过校验
if($form.data('bootstrapValidator').isValid()){
$.post($form.attr('action'), $form.serialize(), function(result) {
console.log(result);
$('#editModal').modal('hide');
listShow(); // 刷新列表
}, 'json');
}
});

DateTimePicker

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
<script src="js/jquery-1.11.1.min.js"></script>
<link href="css/bootstrap.css" rel='stylesheet' type='text/css' />
<script src="js/bootstrap.js"></script>
<link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" media="all">
<script src="js/bootstrap-datetimepicker.min.js"></script>

<div class="bottom-form">
<div class="col-md-3 grid-form">
<h5>开始时间</h5>
</div>
<div class="col-md-9 grid-form1">
<input id="startTime" name="startTime" class="form_datetime" type="text" required readonly>
</div>
<div class="clearfix"></div>
</div>

$('.form_datetime').datetimepicker({
format: 'yyyy-mm-dd hh:ii', // 格式
minView: 0, // 最小时间界面 0 分钟;1 小时;2 日期
weekStart: 1,
todayBtn: 1,
autoclose: 1,
todayHighlight: 1,
startView: 2, // 起始时间界面 0 分钟;1 小时;2 日期
forceParse: 0,
showMeridian: 1
}).on('hide',function(e) {
// 当日期选择框关闭时,执行刷新校验;与bootstrapValidator一起使用时需要注意的点
$('#editForm').data('bootstrapValidator')
.updateStatus('startTime', 'NOT_VALIDATED',null)
.validateField('startTime')
.updateStatus('endTime', 'NOT_VALIDATED',null)
.validateField('endTime');
});

其他知识点

CoffeeScript

1. 是一门编译到 JavaScript 的小巧语言

CoffeeScript

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
# 赋值:
number = 42
opposite = true

# 条件:
number = -42 if opposite

# 函数:
square = (x) -> x * x

# 数组:
list = [1, 2, 3, 4, 5]

# 对象:
math =
root: Math.sqrt
square: square
cube: (x) -> x * square x

# Splats:
race = (winner, runners...) ->
print winner, runners

# 存在性:
alert "I knew it!" if elvis?

# 数组 推导(comprehensions):
cubes = (math.cube num for num in list)

编译后输出的 JavaScript

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
var cubes, list, math, num, number, opposite, race, square,
__slice = [].slice;

number = 42;

opposite = true;

if (opposite) {
number = -42;
}

square = function(x) {
return x * x;
};

list = [1, 2, 3, 4, 5];

math = {
root: Math.sqrt,
square: square,
cube: function(x) {
return x * square(x);
}
};

race = function() {
var runners, winner;
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
return print(winner, runners);
};

if (typeof elvis !== "undefined" && elvis !== null) {
alert("I knew it!");
}

cubes = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = list.length; _i < _len; _i++) {
num = list[_i];
_results.push(math.cube(num));
}
return _results;
})();

2. 安装

1
cnpm install -g coffee-script

3. 用法

官网

运行 coffee 命令以执行脚本, 编译 .coffee 文件到 .js 文件, 和提供一个交互式的 REPL

1
coffee --compile --output lib/ src/

基础知识点

GZIP和BASE64的解压解密

1. GZIP解压

使用pako

1
<script src="resources/js/pako.min.js" charset="utf-8"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var pako = window.pako;
// 必须使用XMLHttpRequest才能请求到arraybuffer类型数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url + '?' + para, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var arrayBuffer = xhr.response; // Note: not xhr.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
var json = pako.inflate(byteArray, { to: 'string' });
json = base64.decode(json);
json = JSON.parse(json);
}
}
};

xhr.send();

2. BASE64解密

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
function Base64() {

// private property
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

// public method for encoding
this.encode = function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
}

// public method for decoding
this.decode = function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = _utf8_decode(output);
return output;
}

// private method for UTF-8 encoding
_utf8_encode = function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}
return utftext;
}

// private method for UTF-8 decoding
_utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

var base64 = new Base64();

// 把param对象变成string带&符号的url参数
function urlEncode(param, key, encode) {
if(param==null) return '';
var paramStr = '';
var t = typeof (param);
if (t == 'string' || t == 'number' || t == 'boolean') {
paramStr += '&' + key + '=' + ((encode==null||encode) ? encodeURIComponent(param) : param);
} else {
for (var i in param) {
var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
paramStr += urlEncode(param[i], k, encode);
}
}
return paramStr;
}

Ajax实现跨域访问的三种方法

1. 处理跨域的方法1 – 代理

比如在北京(www.beijing.com/sever.php)和上海(www.shanghai.com/sever.php)各有一个服务器,北京的后端(www.beijing.com/sever.php)直接访问上海的服务,然后把获取的响应值返回给前端。也就是北京的服务在后台做了一个代理,前端只需要访问北京的服务器也就相当与访问了上海的服务器。这种代理属于后台的技术。

2. 处理跨域的方法2 – JSONP

假设在http://www.aaa.com/index.php这个页面中向http://www.bbb.com/getinfo.php提交GET请求,那么我们在www.aaa.com页面中添加如下代码:

1
2
3
4
var eleScript= document.createElement("script"); //创建一个script元素
eleScript.type = "text/javascript"; //声明类型、
eleScript.src = "http://www.bbb.com/getinfo.php"; //添加src属性 引入跨域访问的url
document.getElementsByTagName("HEAD")[0].appendChild(eleScript); //在页面中添加新创建的script元素

当GET请求从http://www.bbb.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://www.aaa.com/index.php页面中的一个callback函数。看下面一个例子:

www.aaa.com页面中:

1
2
3
4
5
6
<script>
function jsonp( json ){
document.write( json.name ); //输出周星驰
}
</script>
<script src="http://www.bbb.com/getinfo.php"></script>

www.bbb.com页面中:

1
jsonp({ "name":"周星驰","age":45 });

也就是在www.aaa.com页面中声明,在www.bbb.com页面中调用。但是JSONP只支持 “GET” 请求,但不支持 “POST” 请求。

3. 处理跨域的方法3 – XHR2(推荐方法)

“XHR2” 全称 “XMLHttpRequest Level2” 是HTML5提供的方法,对跨域访问提供了很好的支持,并且还有一些新的功能。

IE10以下的版本都不支持

只需要在服务器端头部加上下面两句代码:

1
2
header( "Access-Control-Allow-Origin:*" );
header( "Access-Control-Allow-Methods:POST,GET" );

关于 “XHR2” 的更多信息大家可以查看官方文档

JavaScript混淆和反混淆工具

1. 混淆工具:

  • YUI Compressor
  • Google Closure Compiler
  • UglifyJS
  • JScrambler

2. 反混淆工具:

  • jsbeautifier.org
  • JSDetox

Thymeleaf里面的th和Spring Security结合进行页面权限配置

1
2
3
4
<li th:if="${#authorization.expression('!isAuthenticated()')}">
<a href="#" data-toggle="modal"
data-target="#changePasswordModal">修改密码</a>
</li>