JS 在web开发的一些操作

编程

JS 在web开发的一些操作

  • 检测暗黑模式
  • 原生 http 请求 及 文件上传操作

js 检测浏览器是否暗黑模式

在浏览器中检测设备是否开启暗黑模式以自动切换暗黑模式

1
2
3
4
5
6
if (window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches) {
console.log('enable dark');
toggleClass();
}

注册监听函数,监听状态改变以检测设备暗黑模式的改变

1
2
3
4
5
6
7
8
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', event => {
if (event.matches) {
//dark mode
} else {
//light mode
}
})

js 原生 http 请求

之前犹豫嫉妒不自信,倾向使用 vue,react 等工具,但是,这使得一个小小的页面也需要加载一堆不需要的依赖项,使得生成文件巨大,尝试过压缩,但是,可能技术不到位,没什么好效果。昨天用原生 html css js 写了一个网页。这里使用原生支持进行 http 请求。

接收响应

一个完整的HTTP响应由 状态码响应头集合响应主体 组成。在收到响应后,这些都可以通过XHR对象的属性和方法使用,主要有以下4个属性

1
2
3
4
responseText: 作为响应主体被返回的文本(文本形式)
responseXML: 如果响应的内容类型是'text/xml'或'application/xml',这个属性中将保存着响应数据的XML DOM文档(document形式)
status: HTTP状态码(数字形式)
statusText: HTTP状态说明(文本形式)

在接收到响应后,第一步是检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态码为200作为成功的标志。此时,responseText属性的内容已经就绪,而且在内容类型正确的情况下,responseXML也可以访问了。此外,状态码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。

无论内容类型是什么,响应主体的内容都会保存到responseText属性中,而对于非 XML 数据而言,responseXML 属性的值将为 null

1
2
3
4
5
6
if((xhr.status >=200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert('request was unsuccessful:' + xhr.status);
}

GET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'url', true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}

POST

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
let data = {
guestRoomID : form.room_id.value,
position : form.room_position.value,
type : form.room_type.value,
power: 1
}
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'url', true);
xmlhttp.setRequestHeader("Content-type", "application/json");
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}

//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send();

//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send(JSON.stringify());

PUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let  xmlhttp = new XMLHttpRequest();
xmlhttp.open('PUT', 'url', true);
xmlhttp.setRequestHeader('Content-type','application/json');
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}

DELETE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let xmlhttp = new XMLHttpRequest();
xmlhttp.open("DELETE", url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(JSON.parse(xmlhttp.response));
let response = JSON.parse(xmlhttp.response);
if (response.status == 200) {
alert("创建成功");
} else {
alert("创建失败");
}
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
alert("网络错误,请稍后重试");
}
}

补充

GET请求

get请求的查询字符串都必须使用encodeURIComponent()编码

1
2
3
4
5
6
function addURLParam(url, name, value) {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}

HTTP请求的时限

有时,ajax操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。

新版本的XMLHttpRequest对象,增加了timeout属性,可以设置HTTP请求的时限。

1
2
xhr.timeout = 3000;

上面的语句,将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout事件,用来指定回调函数。

1
2
3
4
xhr.ontimeout = function(event){
  alert('请求超时!');
}

不过在超时后访问status属性则会发生错误,可以把检查status的语句放到try/catch中。

目前,Opera、Firefox和IE 10支持该属性,IE 8和IE 9的这个属性属于XDomainRequest对象,而Chrome和Safari还不支持。

1
2
3
4
5
6
7
xhr.open('post','test.php',true);
xhr.ontimeout = function(){
console.log('The request timed out.');
}
xhr.timeout = 1000;
xhr.send();

FormData对象

ajax操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个FormData对象,可以模拟表单。这一部分可参考之前发的《nodejs 上传文件到七牛云》

首先,新建一个FormData对象。

1
var formData = new FormData();

然后,为它添加表单项。

1
2
formData.append('username', '张三');
formData.append('id', 123456);

最后,直接传送这个FormData对象。这与提交网页表单的效果,完全一样。

1
xhr.send(formData);

FormData对象也可以用来获取网页表单的值。

1
2
3
4
5
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一个表单项
xhr.open('POST', form.action);
xhr.send(formData);

上传文件

新版XMLHttpRequest对象,不仅可以发送文本信息,还可以上传文件。

假定files是一个”选择文件”的表单元素(input[type=“file”]),我们将它装入FormData对象。

1
2
3
4
5
6
7
var formData = new FormData();

  for (var i = 0; i < files.length;i++) {

    formData.append('files[]', files[i]);

  }

然后,发送这个FormData对象。

1
xhr.send(formData);

进度事件的种类

进度事件用来描述资源加载的进度,主要由 AJAX 请求、<img><audio><video><style><link>等外部资源的加载触发,继承了ProgressEvent接口。它主要包含以下几种事件。

  • abort:外部资源中止加载时(比如用户取消)触发。如果发生错误导致中止,不会触发该事件。
  • error:由于错误导致外部资源无法加载时触发。
  • load:外部资源加载成功时触发。
  • loadstart:外部资源开始加载时触发。
  • loadend:外部资源停止加载时触发,发生顺序排在error、abort、load等事件的后面。
  • progress:外部资源加载过程中不断触发。
  • timeout:加载超时时触发。

MIME类型

媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 / 多功能网际邮件扩充协议)是一种标准,用来表示文档、文件或字节流的性质和格式。

网络中媒体一种格式, 在http协议中, 不认识后缀名, 只认识MIME类型, 只要你设置对MIME类型,浏览器会用指定的引擎解析对应的数据。在HTTP中,MIME类型被定义在Http响应的响应头 的Content-Type字段中。(network->head)

MIME意为多目Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。
访问一个网页,获得一个资源后,浏览器通过媒体资源类型MIME Type,媒体资源类型通过http协议,由web服务器告知浏览器,更详细的说,是通过Content-Type来定义的。
例如:Content-Type: text/HTML
通常只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。

怎么获得MimeType

servletContext.getMimeType(file.getName());

这个方法会根据文件名自动分割出文件的后缀名,并且根据后缀名去tomcat/conf/web.xml中查取的对应关系,并返回。

服务器传到客户端的文件mime类型的详细过程:

Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览 器,以进行识别。

由于MIME类型与文档的后缀相关,因此服务器使用文档的后缀来区分不同文件的MIME类型,服务器中必须定义文档后缀 和MIME类型之间的对应关系。而客户程序从服务器上接收数据的时候,它只是从服务器接受数据流,并不了解文档的名字,因此服务器必须使用附加信息来告诉 客户程序数据的MIME类型。服务器在发送真正的数据之前,就要先发送标志数据的MIME类型的信息,这个信息使用Content-type关键字进行定义,例如对于HTML文档,服务器将首先发送以下两行MIME标识信息,这个标识并不是真正的数据文件的一部分。

1
2
3
Content-type: text/html
空行 “ ”

注意,第二行为一个空行,这是必须的,使用这个空行的目的是将MIME信息与真正的数据内容分隔开。


浏览器编码

“只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*‘(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。

由HTML源码中字符集的设定决定。

1
<meta http-equiv="Content-Type" content="text/html;charset=xxxx">

如果上面这一行最后的charset是UTF-8或是GB2312,URL就以对应的编码。GET和POST方法的编码,用的是网页的编码。

escape()不对“+”编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。

方法一:escape()

escape()来编码字符串;unescape()来解码字符串;

方法二:encodeURIComponent()

encodeURIComponent()编码,decodeURIComponent()进行解码;
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。

该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ’ ( ) 。

其他字符(比如 :;/?😡&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var test1="http://www.example.com/My first/";
var nn=encodeURI(test1);
var now=decodeURI(test1);

http://www.example.com/My%20first/
http://www.example.com/My first/

var test1="http://www.example.com/My first/";
var bb=encodeURIComponent(test1);
var nnow=decodeURIComponent(bb);

http%3A%2F%2Fwww.example.com%2FMy%20first%2F
http://www.example.com/My first/

Author: 哒琳

Permalink: http://blog.jieis.cn/2022/7ec92801-35f8-4d70-91a1-bdc7e4fdb24f.html

Comments