JavaScript 基础-操作浏览器

JS 是为网页开发而设计的语言,可以使用 JS 操作网页中的元素对象,来实现网页的动态效果与逻辑。本篇对 JS 中自带的浏览器对象进行介绍,并介绍 jQuery 库,用于更加方便的操作网页对象。

JS 的运行引擎就是浏览器。常见的浏览器 JS 引擎包括 Chrome 的 V8 引擎,Firefox 的 SpiderMonkey 引擎等。

使用 JS 实现网页的动态效果、逻辑运算,首先需要将 JS 代码绑定到网页的特定元素上(或者网页的加载事件前后)。

1. JS 原生方法

JS 中将网页中的重要元素都封装为了特定的对象。例如:

  • 浏览器窗口:window
  • 浏览器信息:navigator
  • 当前页面 URL 信息:location
  • 当前页面对象(DOM):document

通过上述对象,JS 可以具体定位到网页中的特定元素,通过 JS 提供的相关方法,可以找到对应元素。下面,介绍 JS 代码操作相关元素的方法。

1.1. 操作DOM

HTML 文档被浏览器解析后,就是一棵 DOM 树,使用 JS 代码,可以实现对 DOM 树相关 更新遍历添加删除 的操作。

通过下面的例子进行演示:

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
/**
* 通过 getElementById(), getElementByTagName(),
* getElementByClassName() 等方法获取对应的元素对象
*/
var p = document.getElementById('p-id');
p.innerHTML = 'ABC';
// innerText, innerContent 更安全,会对特殊字符进行自动转义
p.innerText = '<script>';

// 下述代码向 list 中添加元素
var
list = document.getElementById('list'),
haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);

// 遍历列表
var
i, c,
list = document.getElementById('list');
// 使用 children 属性
for (i = 0; i < list.children.length; i++) {
c = list.children[i]; // 拿到第i个子节点
}

1.2. 操作表单、文件

表单作为一种 HTML 中一种特殊的元素,JS 提供了一些额外的属性来获取表单中的用户输入值等。例如:

1
2
3
// <input type="text" id="email">
var input = document.getElementById('email');
var val = input.value; // 获取用户输入的值

同时可以在提交表单时,绑定相关的 JS 代码对表单内容进行一些合法性判断等。例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>

<script>
function checkForm() {
var form = document.getElementById('test-form');
// 可以在此检查、修改 form的input...
return true;
}
</script>

需要注意的是,只有当 JS 代码返回 true,表单才会继续提交。因此在 JS代码中可以对表单的合法性进行判断,如果判断不合法,返回 false,阻止表单的提交。

此外,HTML 中使用 <input type='file'> 来读取文件对象。JS 可以使用 FileFileReader 对象,来分别对文件信息和文件内容进行读取。

1.3. AJAX

AJAX 是 “Asynchronous JavaScript and XML” 的缩写,意思就是用 JavaScript 执行异步网络请求。它不是一种编程语言,而是一种标准和方法。

设想如下的情景:在 HTML 中提交 form 表,用户点击 submit 按钮后,表单提交开始,然后在新的页面中告知你操作是否成功。如果网络太慢等因素造成传输失败,可能得到一个 404 页面。这是 Web 的运作原理造成的,一次 HTTP 请求对应一个页面。

如果想让用户留在当前的页面,同时发出新的 HTTP 请求,则必须用 JS 发送这个新的请求。接收到数据后,再用JS更新页面。

上述需求催生了 AJAX 技术。AJAX 一般通过 XMLHttpRequest 对象来实现。JS 代码通过该对象构造一个 Http Request 请求,然后异步地执行,通过 回调函数 确定获得 response 之后浏览器的动作。参考下面的代码:

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
function success(text) {
var textarea = document.getElementById('test-response-text');
textarea.value = text;
}
function fail(code) {
var textarea = document.getElementById('test-response-text');
textarea.value = 'Error code: ' + code;
}

var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象
request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}
// 发送请求:
request.open('GET', '/api/categories');
request.send();

上述代码中,通过 request 对象的 onreadystatechange 属性来设置回调函数。回调函数中则通过响应代码判断响应是否正确。

需要注意的是,上述发送的 Http request 只允许请求与当前浏览器中页面域名相同的资源(出于安全考虑的规定)。如果需要访问其他站点,有如下三种方法:

  1. 在服务器端处理,在同原域名下架设一个代理转发服务器;
  2. 使用 JSONP,也就是动态的在 HTML 头部添加 JS 代码;
  3. 借助 HTML5 提供的 CORS(Cross-Origin-Resource Sharing) 规范进行跨域间的访问。

异步任务的处理是网络编程的重点之一。JS 的单线程特点也使得其经常需要处理异步代码问题。

从ES6 开始,可以通过 promise 对象来优化异步代码的实现(代替回调函数的实现方法)。例子如下:

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
new Promise(functon(resolve, reject){
log('Start new Promise...');
var timeOut = Math.random() * 2;
log('Set timeout to: ' + timeout + ' seconds.');
setTimeout(function(){
if(timeOut <> 1){
log('Call resolve() ...');
resolve('200 OK');
}else{
log('Call reject() ...');
reject('timeOut!!');
}
}, timeOut * 1000);
}).then(function(r){ // r 为resolve 函数中传入的内容
log('Done' + r);
}).catch(function(reason){ // reason为 reject 函数中传入的内容
log('Failed' + reason);
});

// promise 函数的框架
new Promise(function(resolve, reject){...异步操作...})
.then(function(r){...执行成功,调用resolve 中传出的参数})
.catch(function(reason){... 执行失败,出现 error 等,调用 reject传入的参数});

// promise 还可以实现多个异步任务的串行执行
// job1, job2, job3 都是 promise 对象
job1.then(job2).then(job3).catch(handleError);

2. jQuery

JQuery 是一个 JavaScript 的库(library)。它的核心作用主要在于下面几个方面:

  • 消除浏览器差异:
  • 提供更简洁的方法操作 DOM 对象。
  • 提供更简单的动画实现和 CSS 样式表修改。

使用 jQuery 的方法很简单,在 HTML 文档的头部添加一句:

1
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>

即可。引用的 jQuery 文件可以放在本地的或者 CDN 提供的文件。注意,.min. 版本是去除了用于调试的相关接口的精简版本,最后用于发布时,需使用 .min. 版本。

实际上,jQuery就是方便了第一部分 JS 代码对于 web 的操作。从来个方面进行介绍,1 - 选择器;2- 处理异步事件。

2.1 选择器

选择器是 jQuery 的核心。可以使用下列方法选中 DOM 中的元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 按 ID 查找
var div = $('#abc');
// 按 tag 查找
var ps = $('p');
// 按 class 查找, 可以同时查找多个
var a = $('.red.green');
// 按 属性查找
var email = $('[name=email]'); // 找出<??? name="email">
// 按 属性的前后缀查找
var icons = $('[name^=icon]'); // 属性 name 的值中前缀为 icon 的
var names = $('[name$=with]'); // 属性 name 中以 with 结尾的
// 多项查找
var tr = $('tr.red'); // 找出<tr class="red ...">...</tr>

使用 jQuery 选择器选中 DOM 元素,返回的是一个 jQuery 对象(相当于将 DOM 元素封装到了一个数组中)。

因此,对于返回后的 jQuery 对象,可以使用统一的 jQuery方法进行查找,过滤等操作。而不再需要考虑不同浏览器的差异。

常用的作用在 jQuery对象上的方法如下:

1
2
3
4
5
6
7
8
9
10
11
// find() 方法:查找, 
var ul = $('ul.lang'); // 获取 jQuery 对象
var dy = ul.find('.dy'); // 根据class 查找
var swf = ul.find('.#swift'); // 根据id 查找
// parent() 获得该结点的父级元素 ,next(), prev() 同一级结点间移动
var parent = swf.parent(); // 获得 swift 的上层节点 <ul>
var sche = swf.next(); // 获取swift 的下个结点 Scheme

// filter() 方法,过滤
var langs = $('ul.lang li'); // 拿到所有语言列表
var a = langs.filter('.dy'); // 筛选出部分语言:JavaScript, Python, Scheme

修改元素内容和样式

获取元素之后,使用下列方法对元素进行修改:

1
2
3
4
5
6
7
8
9
// 获取和修改 元素内容
$('#test-ul li[name=book]').text(); // 'Java & JavaScript'
$('#test-ul li[name=book]').html(); // 'Java &amp; JavaScript'
var j1 = $('#test-ul li.js');
// 替换 'JavaScript' 文字部分,将字体变为红色
j1.html('<span style="color: red">JavaScript</span>');

// 修改 样式
$('#test-css li.dy>span').css('background-color', '#ffd351').css('color', 'red');

2.2 事件响应

使用 jQuery 绑定 DOM 元素事件时,一定要等到 DOM 加载完毕后再进行(document 对象的 ready 事件中进行)。例如:

1
2
3
4
// 绑定 form 的 submit 事件
$('#testForm').submit(function(){...});
// 绑定 button 的 click 事件
a.click(function(){ console.log('Hello!'); });

使用 jQuery 处理 AJAX 也很方便,jQuery 在全局对象 jQuery(也就是 $) 上绑定了 ajax() 函数,可以直接处理 AJAX 请求,如下:

1
2
3
4
5
6
7
8
9
10
11
// ajax 函数接收两个参数:1- request 的 URL
// 2- request 的相关参数,例如 json 数据,request 方法等
var jqxhr = $.ajax('/api/categories', {
dataType: 'json'
});

// 简化方法,直接发送 get 请求
var jqxhr = $.get('/path/to/resource', {
name: 'Bob Lee',
check: 1
});

jQuery 还提供了函数功能封装的解决方案,通过扩展 $.fn 对象来实现。