我们在做移动端项目的时候,经常会遇到手机旋转的一些事件,对于安卓手机,在QQ和微信中我们可以用下面这行代码禁止浏览器横屏(安卓手机的QQ和微信用的都是X5浏览器):

1
<meta name="x5-orientation" content="portrait">

UC浏览器强制竖屏:

1
<meta name="screen-orientation" content="portrait">

但是在iphone里面我们是没办法禁止浏览器横屏,换句话说就是没办法禁止浏览器旋转。

所以我们就需要判断当前处于横屏还是竖屏,并且增加监听事件,当屏幕旋转的时候触发相应的事件。

测试媒体查询

我们可以使用 媒体查询 来实现上述的功能。DOM可以通过程序来获得媒体查询的结果。这是通过 MediaQueryList 接口和它的方法来实现的。要创建 MediaQueryList 对象来存放媒体查询需要使用window.matchMedia 方法。

window.matchMedia

概要

返回一个新的MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。

语法

1
screenDirection = window.matchMedia(mediaQueryString)

其中mediaQueryString参数是一个字符串,表示即将返回一个新MediaQueryList对象的媒体查询。针对于我们本文打横竖屏的判断,我们可以按照如下这种方式判断:

1
var screenDirection = window.matchMedia("(orientation: portrait)");

返回值是:
screenDirection的结果

MediaQueryList

MediaQueryList对象在document上维持着一系列的媒体查询,并负责处理当媒体查询在其document上发生变化时向监听器进行通知的发送。(据此我们就可以检测横竖屏,并且当横竖屏改变的时候触发相应的事件)。

属性

  1. matches:返回的是一个boolean,为true则表示当前的document匹配media query list也就是上面的mediaQueryString,否则返回false。依然用上面的例子说,返回true则表示处于portrait(竖屏),false则表示处于landscape(横屏)。
  2. media:表示我们上面例子中的mediaQueryString,例如上面例子screenDirection.media等于"(orientation: portrait)"
  3. onChange:该mediaquerylist接口onChange属性是一个事件处理程序属性代表一个函数,调用时的变化的事件触发,即当媒体查询支持改变现状。事件对象是一个mediaquerylistevent实例,这是公认的在旧的浏览器medialistquery实例,向后兼容的目的。下面是一个onChange的例子(可以copy到本地试试看):
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">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MediaQueryList</title>
</head>
<body>
<p></p>
<script>
var para = document.querySelector('p');
var mql = window.matchMedia('(max-width: 600px)');
mql.onchange = function (e) {
if (e.matches) {
/* the viewport is 600 pixels wide or less */
para.textContent = 'This is a narrow screen — less than 600px wide.';
document.body.style.backgroundColor = 'red';
} else {
/* the viewport is more than than 600 pixels wide */
para.textContent = 'This is a wide screen — more than 600px wide.';
document.body.style.backgroundColor = 'blue';
}
}
</script>
</body>
</html>

实际效果是:打开屏幕不管多大多小都没有触发任何事件,我们改变屏幕的大小,只有当第一次满足max-width: 600px之后触发onchange 中的true的事件,之后才会触发false的事件,按照官方的说法这是公认的在旧的浏览器medialistquery实例,向后兼容的目的,所以我们还是不用它。

方法

  1. addListener():在媒体查询列表上增加一个新的监听器,如果列表中已经存在了这个指定的监听器,这个方法将失去作用。
  2. removeListener():从媒体查询列表中移除一个监听器,如果列表中不存在这个指定的监听器,则这个方法将失去作用。

所以我们可以在MediaQueryList添加addListener()方法,当其横竖屏发生变化的时候执行相应的事件。so完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var screenDirection = window.matchMedia("(orientation: portrait)");

screenDirection.addListener(handleOrientationChange);

handleOrientationChange(screenDirection);

function handleOrientationChange(screenDirection) {
if (screenDirection.matches) {
/* The device is currently in portrait orientation */
/* 竖屏处理事件 */
} else {
/* The device is currently in landscape orientation */
/* 横屏屏处理事件 */
}
}

上述代码创建了一个屏幕方向的测试查询列表screenDirection,并且添加了事件监听。需要注意的是,当我们添加监听后,我们其实直接调用了一次监听。这会让我们的监听器以目前设备的屏幕方向来初始化判定代码。然后,我们可以在handleOrientationChange() 方法中来查看查询结果,并且可以设置屏幕方向变化后的逻辑处理代码。

场景

jquery多css选择器获取指定元素,相信你看到这一定会问一个id就搞定的事干嘛扯这么多,但是某些情况下就很无奈呀,就比如今天一哥们问我,一个元素上面有两个class,要怎么获取这个元素,我第一反应也是扔个id上去多好简单粗暴,结果他回答说,这是修改老项目,html不让动,这就很无奈。

代码

既然使用jquery,那第一反应就是符合属性选择器喽~

1
[selector1][selector2][selectorN]

复合属性选择器,需要同时满足多个条件时使用。

比如说我们要用复合属性选择器筛选下面这个元素:

1
<div class="header nav"></div>

我们就可以用下面这种方法去匹配:

1
$(".header.nav")

之后我又想也可以[attribute=value] 去匹配呀:

1
$("[class='header nav']")

jQuery还提供了filter()呀,so:

1
$(".header").filter("nav").prevObject

实际上第一种复合属性选择器的用处远不止上面那么简单,我们也可以像如下去匹配:
比如有很多a标签,但我们只需要class是cur的a标签:

1
$("a.cur")

或者是查找name属性是username的input标签:

1
$("input[name='username']")

那么再加上css里面的伪类,获取所有未选中的 input 元素:

1
$("input:not(:checked)")

也就是复合属性选择器可以使用element/.class/[attribute]等多种选择器去任意组合出你想要的模式。

缘由

我们在做移动端项目,尤其是在微信里面的时候,会经常遇到判断是否处于微信浏览器,并且当不处于微信浏览器的时候要提示请在微信客户端打开链接。

在这里我们一般都会判断navigator.userAgent,看其中是否包含micromessenger字符串,如果包含则处于微信浏览器,如若不包含,则处于其他浏览器。

可以点击查看例子

代码

1
2
3
4
5
6
var ua = navigator.userAgent.toLowerCase();
var isWeixin = ua.indexOf('micromessenger') != -1;
if (!isWeixin) {
document.head.innerHTML = '<title>抱歉,出错了</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"><link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css">';
document.body.innerHTML = '<div class="weui_msg"><div class="weui_icon_area"><i class="weui_icon_info weui_icon_msg"></i></div><div class="weui_text_area"><h4 class="weui_msg_title">请在微信客户端打开链接</h4></div></div>';
}

将table数据转为Excel表格放到前端来做可以减少服务器的压力,而且不受网速影响,速度响应快。

例子

  1. 原生js实现table数据转为Excel表格
  2. jquery.table2excel.js实现table数据转为Excel表格

主体函数

原生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
function getExplorer() {
var explorer = window.navigator.userAgent;
//ie
if (explorer.indexOf("MSIE") >= 0) {
return 'ie';
}
//firefox
else if (explorer.indexOf("Firefox") >= 0) {
return 'Firefox';
}
//Chrome
else if (explorer.indexOf("Chrome") >= 0) {
return 'Chrome';
}
//Opera
else if (explorer.indexOf("Opera") >= 0) {
return 'Opera';
}
//Safari
else if (explorer.indexOf("Safari") >= 0) {
return 'Safari';
}
}

function method(tableid) {
var fileName = document.getElementById("fileName").value.replace(/\s/g, "");
if (getExplorer() == 'ie') {
// 一种方法,但是没办法修改文件名
// var curTbl = document.getElementById(tableid);
// var oXL = new ActiveXObject("Excel.Application");
// var oWB = oXL.Workbooks.Add();
// var oSheet = oWB.ActiveSheet;
// var Lenr = curTbl.rows.length;
// for (i = 0; i < Lenr; i++) {
// var Lenc = curTbl.rows(i).cells.length;
// for (j = 0; j < Lenc; j++) {
// oSheet.Cells(i + 1, j + 1).value = curTbl.rows(i).cells(j).innerText;
// }
// }
// oXL.Visible = true;


// 第二种方法,可命名文件名
try {
var winname = window.open('', '_blank', 'top=10000');
var strHTML = document.getElementById(tableid).innerHTML;

winname.document.open('application/vnd.ms-excel', 'export excel');
winname.document.writeln(strHTML);
winname.document.execCommand('saveas', '', fileName + '.xls');
winname.close();
} catch (e) {
alert(e.description);
}

} else {
tableToExcel(tableid, fileName);
}
}
var tableToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,',
template = '<html><head><meta charset="UTF-8"></head><body><table>{table}</table></body></html>',
base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)));
},
format = function (s, c) {
return s.replace(/{(\w+)}/g,
function (m, p) {
return c[p];
})
};
return function (table, fileName) {
if (!table.nodeType) {
table = document.getElementById(table);
}
var dlink = document.getElementById("dlink");
var ctx = {
worksheet: fileName ? fileName : 'Worksheet',
table: table.innerHTML
}
dlink.href = uri + base64(format(template, ctx));
dlink.download = fileName + ".xls";
dlink.click();
}
})()

使用jquery.table2excel.js的方式为:

1
2
3
4
5
6
7
8
9
10
11
$("#btnExport").click(function () {
$("#tableExcel").table2excel({
exclude: ".noExl", //过滤位置的 css 类名
filename: $.trim($("#fileName").val()) + ".xls", //文件名称
name: "Excel Document Name.xlsx",
exclude_img: true,
exclude_links: true,
exclude_inputs: true

});
});

关于jquery.table2excel.js还可前去其github查看。

location对象中search属性返回的是问号之后的URL,这部分通常是某种类型的查询字符串,是用来参数化URL并在其中嵌入参数的,那么如何在页面中用js来获取到所有的参数呢?下面的函数就是为此而生:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 函数用来解析来自URL的产讯传中的name = value参数对,并将其存储在一个对象的属性中,并且返回该对象
function urlArgs(){
var args = {};
var query = location.search.substring(1);
var pairs = query.split("&");
for(var i = 0;i < pairs.length; i++){
var pos = pairs[i].indexOf("=");
if(pos == -1) continue;
var name = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos + 1);
value = decodeURIComponent(value);
args[name] = value;
}
return args;
}
/*
* 使用方法
* var args = urlArgs();
* var q = args.q || "";
* var n = args.n ? parseInt(args.n) : 10;
*/