AJAX
AJAX的全称是Asynchronous JavaScript and XML
,就是异步响应网络的请求,从字面意思上看,AJAX是异步执行的,AJAX需要借助于XMLHttpRequest对象
发送AJAX请求时,域名必须和当前页面完全一致,即
1、协议相同(http和https不同)
2、端口相同
AJAX请求外域有下面几种方法:
1、使用Flash插件发送HTTP请求,这种方法可以绕过浏览器的安全限制,但必须安装Flash
2、在同源域名下架设一个代理服务器来转发,JavaScript负责把请求进行转发到代理服务器:
'/proxy?url=http://www.sina.com.cn'
3、使用JSONP,但是这个方式只能用GET请求
HTML
<p id="test-jsonp"></p>
<button type="button" onclick="getPrice()">刷新</button>
JavaScript
function refreshPrice(data) {
var p = document.getElementById('test-jsonp');
p.innerHTML = '当前价格:' +
data['0000001'].name +': ' +
data['0000001'].price + ';' +
data['1399001'].name + ': ' +
data['1399001'].price;
}
function getPrice() {
var
js = document.createElement('script'),
head = document.getElementsByTagName('head')[0];
js.src = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
head.appendChild(js);
}
4、CORS:最新的浏览器全面支持HTML5,在引用外语资源时,除了JavaScript和CSS外,都要验证CORS,它的过程是这样的,当JavaScript向外域发出请求,浏览器收到响应后,首先检查Access-Control-Allow-Origin
是否包含本域,如果包含,则请求成功,反之,请求失败,就是说,决定权在服务器端
Promise
Promise是一种对程序的异步处理结果进行处理的对象,由浏览器直接支持
Promise的作用是这样的,它把执行代码和对代码执行结果处理进行了分离,看下面一个例子
HTML
<ul id="test-promise-log"></ul>
<script type="text/javascript">PromiseTest1();</script>
JavaScript
//初始化log
function initLogging(){
var logging = document.getElementById('test-promise-log');
while(logging.children.length > 1){
logging.removeChild(logging.children[logging.children.length - 1]);
}
}
//添加log
function log(s){
var logging = document.getElementById('test-promise-log');
var p = document.createElement('p');
p.innerHTML = s;
logging.appendChild(p);
}
//执行Promise的测试
function PromiseTest1(){
initLogging();//首先进行初始化操作
new Promise(function(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 in ' + timeOut + ' seconds.');
}
},timeOut * 1000);
}).then(function(r){
log('Done:' + r);
}).catch(function(reason){
log('Failed:' + reason);
});
}
上面的代码是一个异步执行的方式,结构大概是这样
new Promise(
function(resolve,reject){
if(条件满足){
resolve('result');
}else{
reject('reson');
}
}).then(function).catch(function);
假如条件满足,执行resolve,被then捕获,假如条件不满足,执行reject,被catch捕获
Promise的常用形式如下面所示,它的执行是这样的,先执行job1,假如执行的结果满足条件,则执行job2,依次下去直到最后一个任务,假如在执行的过程中,有一个不满足,则被捕获
job1.then(job2).then(job3).catch(handleError);
看下面一个例子
HTML(同上)
JavaScript
//执行乘法
function multiply(input){
return new Promise(function(resolve,reject){
log('calculating ' + input + ' x ' + input + '...');
setTimeout(resolve,500,input * input);
});
}
//执行加法
function add(input){
return new Promise(function(resolve,reject){
log('calculating ' + input + ' + ' + input + '...');
if(input < 10000)
setTimeout(resolve,500,input + input);
else
setTimeout(reject,500,input);
});
}
function PromiseTest2(){
var p = new Promise(function(resolve,reject){
log('start new Promise...');
resolve(123);
});
p.then(multiply)
.then(add)
.then(multiply)
.then(add)
.then(function(result){
log('Got value:' + result);
}).catch(function(r){
log('Number is too big:' + r);
});
}
Promise.all([p1,p2]).then();//这个方法是让数组中的两个Promise对象都进行返回之后,然后再执行then中的方法,代码如下
function PromiseTest3(){
var p1 = new Promise(function(resolve,reject){
setTimeout(resolve,Math.random() * 100,'P1');
});
var p2 = new Promise(function(resolve,reject){
setTimeout(resolve,Math.random() * 100,'P2');
});
Promise.all([p1,p2]).then(function(results){
alert(results);
});
}
Promise.race([p1...pn]).then();//这个则是对数组中的Promise对象进行执行,then的执行条件是其中最先执行完的一个Promise对象,代码同上,把all改为race即可
Canvas
是HTML5新增的组件,像是一块幕布,可以使用JavaScript在其中绘制各种图表、动画等
1、首先我们需要创建一个canvas
节点
2、我们使用获取getElemeById
的方式来获取这个画布
3、使用canvas.getContext('2d')
;//来获取这个画布的句柄,接着就能操作这个画布了
如下
绘制一个图形
HTML
<canvas id="test-canvas-1" width="300" height="200">
</canvas>
<script type="text/javascript">CanvasTest1();</script>
JavaScript
//画一个笑脸
function CanvaPaintSmileFace(){
var canvas = document.getElementById('test-canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,200,200);
ctx.fillStyle = '#dddddd';
ctx.fillRect(10,10,130,130);
var path = new Path2D();
path.arc(75,75,50,0,Math.PI*2,true);
path.moveTo(110,75);
path.arc(75,75,35,0,Math.PI,false);
path.moveTo(65,65);
path.arc(60,65,5,0,Math.PI*2,true);
path.moveTo(95,65);
path.arc(90,65,5,0,Math.PI*2,true);
ctx.strokeStyle = '#0000ff';
ctx.stroke(path);
}
绘制一个文本
HTML(同上)
JavaScript
//文本绘制
function CanvasTest2(){
var canvas = document.getElementById('test-canvas-1'),
ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = '#666666';
ctx.font = '24px Arial';
ctx.fillStyle = '#333333';
ctx.fillText('Something Just Happens',20,40);
}
JQuery
作用
1、消除浏览器差异,不需要写冗长的代码来针对不同的浏览器进行优化
2、简洁的操作DOM的方法
3、轻松实现动画、修改CSS等各种操作
jQuery的使用只要在head下面添加下面这句就可以了
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
$符号
$是jQuery的别名,本质上是一个函数
选择器
$('#dom-id');//按照id进行查找,返回的是一个数组,而不是undefined或者null,所以不用进行判断
var div = $('#domid');
var divDom = div.get(0);//假设存在,获取第一个DOM元素
var another = $(divDom);//将DOM包装为jQuery对象
$('tag-name');//按照tag进行查找,返回的是一个数组
var ps = $('p');
ps.length;
$('.class-name');//按照class进行查找
var a = $('.red.green');
$('[name=email]');//按照属性进行查找
$('[name^=icon]');//找出所有以icon开头的属性
$('[name$=with]');//找出所有以with结尾的属性
$('[class^=icon-]');//找出所有以icon-开头的class属性
$('p.red,div.green');//找出所有tag为p且class为red和tag为div和class为green的属性
$('input[name=email]');//找出所有input中name为email的属性
看一个实例
HTML
<!--选择器-->
<div id="test-jquery">
<p id="para-1" class="color-red">JavaScript</p>
<p id="para-2" class="color-green">Haskell</p>
<p class="color-red color-green">Erlang</p>
<p name="name" class="color-black">Python</p>
<form class="test-form" target="_blank" action="#0" onsubmit="return false;">
<legend>注册新用户</legend>
<fieldset>
<p><label>名字: <input name="name"></label></p>
<p><label>邮件: <input name="email"></label></p>
<p><label>口令: <input name="password" type="password"></label></p>
<p><button type="submit">注册</button></p>
</fieldset>
</form>
</div>
<input type="text" id="get-val">
<button type="button" onclick="jQueryHandle()">点击</button>
JavaScript
//jQuery的选择器
function jQueryHandle(){
var type = -1;
var num = $('#get-val');
type = Number(num.val());//默认将字符串转化为数字
var selected = null;
switch(type){
case 1://仅选择JavaScript
selected = $('#para-1');
break;
case 2://仅选择Erlang
selected = $('.color-red.color-green');
break;
case 3://选择JavaScript和Erlang
selected = $('.color-red');
break;
case 4://选择所有编程语言
selected = $('[class^=color-]');
break;
case 5://选择名字
selected = $('input[name=name]');
break;
case 6://选择邮件和名字
selected = $('input[name=email],input[name=name]');
break;
default:
return alert('无效操作');
}
if(!(selected instanceof jQuery)){
return alert('不是有效的jQuery对象')
}
$('#test-jquery').find('*').css('background-color','');
selected.css('background-color', '#ff0051');
}
层级选择器
层级之间可以用空格隔开,如下
$('ul.lang li.lang-javascript');//选择class为lang下的class为lang-javascript的所有属性,不同层级之间可以用逗号隔开
子选择器
子选择器类似于层级选择器,但是限定了层级关系必须是父子关系
$('ul.lang>li.lang-javascript');//选出了ul中class为lang中的子class为lang-javascript的属性
过滤器
过滤器一般不单独使用,而是附加在选择器上,如下
$('ul.lang li');//选择class为lang下的所有li
$('ul.lang li:first-child');//选择class为lang下的第一个li
$('ul.lang li:last-child');//选择class为lang下的最后一个li
$('ul.lang li:nth-child(even)');//选择class为lang下的所有奇数li
$('ul.lang li:nth-child(2)');//选择class为lang下的第2个li
表单相关
:input;//可以选择<input>,<textarea>,<select>和<button>
:file;//可以选择<input type="file">
:checkbox;//可以选择复选框
:radio;//可以选择单选框
:focus;//可以选择当前输入焦点的元素
:checked;//选择当前勾上的单选框和复选框
:enabled;//选择正常输入的input
:disabled;//和:enabled正好相反
看下面一个例子
HTML
<div class="test-selector">
<ul class="test-lang">
<li class="lang-javascript">JavaScript</li>
<li class="lang-python">Python</li>
<li class="lang-lua">Lua</li>
</ul>
<ol class="test-lang">
<li class="lang-swift">Swift</li>
<li class="lang-java">Java</li>
<li class="lang-c">C</li>
</ol>
</div>
<input type="text" id="get-val1">
<button type="button" onclick="jQueryHandle2()">点击</button>
JavaScript
//jQuery的层级选择器
function jQueryHandle2(){
var type = -1;
var num = $('#get-val1');
type = Number(num.val());
var selected = null;
switch(type){
case 1://所有语言
selected = $('div.test-selector li[class^=lang]');
break;
case 2://所有动态语言
selected = $('ul.test-lang li');
break;
case 3://所有静态语言
selected = $('ol.test-lang li');
break;
case 4://JavaScript
selected = $('ul.test-lang li:first-child');
break;
case 5://Lua
selected = $('ul.test-lang li:last-child');
break;
case 6://C
selected = $('ol.test-lang li:nth-child(2)');
break;
default:
return alert('无效操作');
}
if(!(selected instanceof jQuery)){
return alert('不是有效的jQuery对象')
}
$('#test-jquery').find('*').css('background-color','');
selected.css('background-color', '#ff0051').css('color', '#ffff00');;
return true;
}
查找和过滤
find();//可以根据当前节点查找子节点
parent();//根据根据当前节点查找父节点
next();//查找当前的节点的下一个节点
prev();//查找当前节点的前一个节点
filter();//过滤出参数中的节点
map();//把节点中的每一个元素转化为其它对象
看一下这个实例,这是将表单转化为json
HTML
<!--查找和过滤-->
<form id="test-form" action="#0" onsubmit="return FindAndFilter();">
<p><label>Name:<input name="name" value="Jack"></label></p>
<p><label>Email:<input name="email" value="m13168793059@163.com"></label></p>
<p><label>Password:<input name="password" value="xiwang"></label></p>
<p>Gender:<label><input type="radio" name="gender" value="m" checked>Male</label>
<label><input type="radio" name="gender" value="f">Female</label>
</p>
<p><label>City:<select name="city">
<option value="BJ">Beijing</option>
<option value="SH">Shanghai</option>
<option value="CD">Chengdu</option>
<option value="XM">Xiamen</option>
</select></label></p>
<p><button type="submit">Submit</button></p>
</form>
JavaScript
//查找和过滤
function FindAndFilter(){
var json = null;
var obj = {};
//对每个节点进行特殊处理
$('input').map(function(){
var key = this.name;
var value = this.value
if(this.name === 'gender')
{
if(this.checked)
obj[`${key}`] = value;
}
else
obj[`${key}`] = value;
});
obj['city'] = $('option:selected').text();
json = JSON.stringify(obj);
if(typeof(json) === 'string')
console.log(json);
else
alert('json变量不是string');
return false;
}
操作DOM
jQuery主要是来操作对应的DOM节点
修改Text和HTML
text();//获取节点的文本,无参数是获取文本,有参数是设置文本
html();//获取节点的原始HTML文本,无参数是获取文本,有参数是设置文本
修改CSS
使用节点的css函数就能对节点的css属性进行修改
$('#test-css li.dy>span').css('background-color','#ffd351').css('color','red');//修改该节点的背景颜色和字体颜色,这是一种链式调用的方式
hasClass('属性');//判断class是否有参数中属性
addClass('属性');//
removeClass('属性');//
看下面一个例子
HTML
<style>
.highlight {
color: #dd1144;
background-color: #ffd351;
}
</style>
<div id="test-highlight-css">
<ul>
<li class="py"><span>Python</span></li>
<li class="js"><span>JavaScript</span></li>
<li class="sw"><span>Swift</span></li>
<li class="hk"><span>Haskell</span></li>
</ul>
</div>
JavaScript
//高亮字符串
function hightlightString(){
var div = $('#test-css');
// div.find('.js').css('background-color','#00ffff').css('color','#ffff00');
div.find('.js').addClass('highlight');
}
显示和隐藏DOM
1、可以设置节点的CSS的display属性为none,不过恢复的时候需要记住原先节点的属性是block还是inline
2、也可以使用hide()函数来隐藏,show()方法来显示
获取DOM的信息
attr();//用来获取节点的属性,或者设置节点的属性(设置属性时参数的个数为2个)
removeAttr();//移除节点的属性
prop();//也是获取节点的属性,但是在处理的时候有所不同
<input id="test-radio" type="radio" name="test" checked="checked" value="1">
var radio = $('#test-radio');
radio.attr('checked');//checked
radio.prop('checked');//true
radio.is(':checked');//true最好的做法
操作表单
jQuery使用val()方法来获取和设置表单元素的属性,如下
/*
<input id="test-input" name="email" value="">
<select id="test-select" name="city">
<option value="BJ" selected>Beijing</option>
<option value="SH">Shanghai</option>
<option value="SZ">Shenzhen</option>
</select>
<textarea id="test-textarea">Hello</textarea>
*/
var
input = $('#test-input'),
select = $('#test-select'),
textarea = $('#test-textarea');
input.val(); // 'test'
input.val('abc@example.com'); // 文本框的内容已变为abc@example.com
select.val(); // 'BJ'
select.val('SH'); // 选择框已变为Shanghai
textarea.val(); // 'Hello'
textarea.val('Hi'); // 文本区域已更新为'Hi'
修改DOM结构
html();//jQuery中的暴力方法,直接对节点进行设置
append();//为节点新增一个子节点,可以添加DOM对象,jQuery对象,函数对象
prepend();//把DOM元素放在最前面
after();//把节点插入到指定位置之后
before();//把节点插入到指定位置之前
删除节点
remove();//直接删除节点
下面的一个例子是对节点进行添加再排序
HTML
<div id="test-div">
<ul>
<li><span>JavaScript</span></li>
<li><span>Python</span></li>
<li><span>Swift</span></li>
</ul>
</div>
<script type="text/javascript">SortNode();</script>
JavaScript
//排序节点
function SortNode(){
var init = ['Pascal','Lua','Ruby'];
var lis = $('#test-div>ul');
lis.find('li').map(function(){
init.push(this.innerText);
this.remove();
});
output(init);
init.sort();
for(var i = 0;i < init.length;i++){
var li = document.createElement('li');
li.innerHTML = '</span>' + init[i] + '</span>';
lis.append(li);
}
}
事件
我们把DOM节点和JavaScript的处理函数进行绑定,那么当我们对节点点击或者键盘输入时,我们就会触发JavaScript中对应的函数
<a id="test-link" href="#0">click me</a>
var a = $('#test-link');
a.on('click',function(){
alert('Hello!');
});
其中on
方法用来对事件的绑定
on();//绑定事件,可以指定事件的类型
click();//直接绑定单击事件
dblclick();//双击事件
mouseenter();//鼠标进入事件
mouseleave();//鼠标离开事件
mousemove();//鼠标移动事件
hover();//鼠标不管进入还是退出都触发事件
keydown();//键盘按下事件
keyup();//键盘松开事件
keypress();//键盘按一次后触发
focus();//DOM获取焦点时触发
blur();//DOM失去焦点时触发
change();//当input、select、textarea的内容修改时触发
submit();//form提交时触发
ready();//页面被载入并且DOM树完成初始化后触发,ready函数的关键就在于将节点的事件绑定到初始化的时候
ready事件的写法
$(function(){
$('#testFom').submit(function(){
alert('submit!');
});
});
事件参数
所有的时间都会传入Event对象作为参数,我们可以对这些对象进行操作
$(function(){
$('#testMouseMoveDiv').mousemove(function(c){
$('#testMouseMoveSpan').text('pageX = ' + e.pageX + ',pageY = ' + e.pageY);
});
});
取消绑定
使用off('click',function)可以解除节点事件的绑定,如下
function hello(){
alert('Hello!');
}
a.click(hello);
//10s之后解除绑定
setTimeout(function(){
a.off('click',hello);
},10000);
事件的触发条件
change函数可以监控事件的触发
var input = $('#test-input');
input.change(function(){
console.log('changed...');
});
input.val('change it!');//这个做法无法触发该事件
input.change();//假如我们调用了JavaScript修改了值,如上面一行,那么我们在这里可以调用无参的change方法来进行调用
浏览器的安全限制
敏感操作将被浏览器拦截,看下面的例子
var btn1 = $('#testbtn1');
var btn2 = $('#testbtn2');
function popupTestWindow(){
window.open('/');
}
btn1.click(function(){
popupTestWindow();
});
btn2.click(function(){
//由于是延迟弹出,将被拦截
setTimeout(popupTestWindow,100);
});
看下面一个例子
HTML
<form id="test-form" action="test">
<legend>请选择想要学习的编程语言:</legend>
<fieldset>
<p><label class="selectAll"><input type="checkbox"> <span class="selectAll">全选</span><span class="deselectAll">全不选</span></label> <a href="#0" class="invertSelect">反选</a></p>
<p><label><input type="checkbox" name="lang" value="javascript"> JavaScript</label></p>
<p><label><input type="checkbox" name="lang" value="python"> Python</label></p>
<p><label><input type="checkbox" name="lang" value="ruby"> Ruby</label></p>
<p><label><input type="checkbox" name="lang" value="haskell"> Haskell</label></p>
<p><label><input type="checkbox" name="lang" value="scheme"> Scheme</label></p>
<p><button type="submit">Submit</button></p>
</fieldset>
</form>
<script type="text/javascript">LanguageHandle();</script>
JavaScript
//实现事件处理的函数
function LanguageHandle(){
var
form = $('#test-form'),
langs = form.find('[name=lang]'),
selectAll = form.find('label.selectAll :checkbox'),
selectAllLabel = form.find('label.selectAll span.selectAll'),
deselectAllLabel = form.find('label.selectAll span.deselectAll'),
invertSelect = form.find('a.invertSelect');
//重置状态
form.find('*').show().off();
form.find(':checkbox').prop('checked', false).off();
deselectAllLabel.hide();
//拦截form提交事件
form.off().submit(function(e){
e.preventDefault();
alert(form.serialize());
});
//对每一个语言都设置选项
langs.click(function(event){
var i = 0;
var out = 0;
for(i = 0;i < langs.length;i++){
var check = langs.get(i).checked;
if(check === false){
out++;
}
}
if(out === 0){
selectAll.prop('checked',true);
selectAllLabel.text('全不选');
}else{
selectAll.prop('checked',false);
selectAllLabel.text('全选');
}
});
//设置全选和全不选
selectAll.click(function(event) {
var i = 0;
var isselected = selectAll.is(':checked');
for(i = 0;i < langs.length;i++){
langs.get(i).checked = isselected;
}
if(isselected === true)
selectAllLabel.text('全不选');
else
selectAllLabel.text('全选');
});
//设置反选
invertSelect.click(function(event) {
var i = 0;
var out = 0;
for(i = 0;i < langs.length;i++){
var check = langs.get(i).checked;
langs.get(i).checked = !check;
if(check)
out++;
}
output(out);
if(out === 0)
{
selectAll.prop('checked',true);
selectAllLabel.text('全不选');
}else{
selectAll.prop('checked',false);
selectAllLabel.text('全选');
}
});
}
动画
show/hide
直接以无参的调用会显示或隐藏DOM元素,添加参数进去,就变成了动画
var div = $('#test-show-hide');
div.hide(3000);//在3秒钟内渐变
div.show('slow');//在0.6秒后慢慢显示
div.toggle('slow');//根据当前状况显示或隐藏
slideUp/slideDown/slideToggle
在垂直方向逐渐展开或收缩
fadeIn/fadeOut/fadeToggle
以淡入或淡出的方式显示
animate
可以实现任意的动画效果,使用的方式如下
var div = $('#test-animate');
div.animate({
//CSS样式
},3000,function(){
//动画完成后的操作
});
//上面的作用是在3s内达到样式表所描述的状态,完成之后调用function
ajax
jQuery在全局对象绑定了ajax(),所以可以处理AJAX请求。ajax(url,settings)是接收AJAx请求的方法,setting的设置有下面几个
async:是否异步执行,默认为true,不要设置为false
method:发送的方法,缺省为GET,也可指定为POST,PUT
contentType:发送POST请求的格式
date:发送的数据,可以是字符串、数组或Object
headers:发送的额外的HTTP头
dataType:接收的数据格式,可以指定为html,xml,json,text
具体的使用
var ajaxh = $.ajax('/api/categories',{
dataType:'json'
});
get
这个方法是针对ajax的GET方法的,写法如下
var jqxhr = $.get('/path/to/resource',{
name:'Bob Lee',
check:1
});
post
和get类似,但是第二个参数被序列化为application/x-www-form-urlencode
var jqxhr = $.post('/path/to/resource',{
name:'Bob Lee',
check:1
});
getJSON
通过get来获取json
var jqxhr = $.getJSON('/path/to/resource', {
name: 'Bob Lee',
check: 1
}).done(function (data) {
// data已经被解析为JSON对象了
});
拓展
编写jQuery插件
错误处理
try...catch...finally,使用的方法和Java一样,不再赘述
错误捕获有3种方式
try...catch...finally;//捕获且最终处理
try...catch;//捕获
try...finally;//没有捕获,都会处理
throw new Error('错误信息'):异常的抛出
错误传播
假如一个程序内部发生了错误,但是它自身没有捕获,错误就会被抛到外层函数,直到被JavaScript引擎捕获,程序终止
异步错误处理
异步执行只是设置了一个响应或者延迟之后再进行操作,因此,我们不能在回调函数外捕获,而是只能在毁掉函数内捕获,如下
try {
$btn.click(function () {
try{
var
x = parseFloat($('#x').val()),
y = parseFloat($('#y').val()),
r;
if (isNaN(x) || isNaN(y)) {
throw new Error('输入有误');
}
r = x + y;
alert('计算结果:' + r);
}catch(e){
alert('输入错误1!');
}
});
} catch (e) {
alert('输入有误2!');
}
如上,我们只能捕获错误1,因为回调函数执行完就退出了,我们捕获的只是响应
underscore
当我们使用Array时,我们有map和filter方法来进行数组的操作,但是对象没有这些好用的方法,另外低版本的浏览器也没有这些方法,我们可以使用undercore来进行这样的操作,这个操作可以让object也可以进行这样的操作