jQuery学习笔记

jQuery大部分功能需要根据文档的DOM模型来工作,首先需要正确地解析到整个文档的DOM模型结构。使用jQuery需要在整个文档被浏览器完全加载后才开始进行。

$(document).ready(function () {
    alert("Hello World!");
    $("p").click(function (event) {
        alert("Thanks for visiting!");
    })
});

$是在jQuery中使用的变量名,可以使用jQuery.noConflict()避免冲突,它的返回值就是jQuery对象。

jQuery.noConflict();
$j = jQuery.noConflict();

jQuery对象与DOM对象之间的转换

使用$()得到的是一个jQuery对象。它封装了很多 DOM 对象的操作,但是它和 DOM 对象之间是不同的。只有当obj是一个DOM对象时才能使用obj.innerHTML;相应地,如果是jQuery对象应该使用 obj.html()

比较正规地从 jQuery 对象到 DOM 的转换,是使用 jQuery 对象的 get() 方法:

$(function () {
    $("li").get();
    $("li").get(0);
    $("li").get(-1);
});

jQuery选择器

1. 常规选择器

2. 属性选择器

3. 控件选择器

4. 其他选择器

节点漫游

1. 调用链处理

$(function () {
    $('ul.first').find('.foo').css('background-color', 'red')
        .end().find('.bar').css('background-color', 'green');
});

2. 子节点

3. 兄弟节点

4. 父节点

元素控制

1. attributesproperties的区别

2. 类与属性控制

$('body').addClass('test');
$('body').addClass(function (index, current) {
    return current + 'new';
});
$('body').removeClass('test');
$('body').removeClass(function (index, current) {
    return current + ' ' + 'other';
});
$('img').toggleClass(); //对所有类的开关
$('img').toggleClass('test'); //对指定类的开关
$('img').toggleClass(isTrue); //根据`isTrue`判断所有类的开关
$('img').toggleClass('test', isTrue); //根据`isTrue`判断指定类的开关

//同 `$('img').toggleClass('test');` 只是类名由函数返回
$('img').toggleClass(function (index, className, isTrue) {
    return 'name'
});

// `isTrue`作为函数的第三个参数传入
$('img').toggleClass(function (index, className, isTrue) {
    return 'name'
}, isTrue);
// $("#greatphoto").attr('alt'); //获取属性`
$("#greatphoto").attr('alt', 'Shenzhen Brush Seller'); //设置属性`

// 同时设置多个属性
$('#greatphoto').attr({
    alt: 'Shen Brush Seller',
    title: 'photo by Kelly Clark'
});

//设置属性为函数返回值,函数的上下文为当前元素
$('#greatphoto').attr('title', function (i, val) {
    return val + ' - photo by Kelly Clark';
})
$('input').val();
$('input').val('other');
$('div').html();
$('div').html('<div>测试</div>');
$('div').html(function (index, old) {
    return old + '<span>另外的内容</span>';
});

3. 样式控制

$('body').css('background-color', 'red');
$('body').css('background-color', function (index, value) {
    return value + '1';
});
$('body').css({color: 'green', 'background-color': 'red'});
$('body').width();
$('body').width(50);
$('body').width(function (index, value) {
    return value += 10;
})

结构控制

1. 文本节点

2. 子节点

$('.inner').append('<p>Test</p>');

参数可以有多种形式:

var $newdiv1 = $('<div id="object1"/>'),
    newdiv2 = document.createElement('div'),
    existingdiv1 = document.getElementById('foo');

$('body').append($newdiv1, [newdiv2, existingdiv1]);

3. 兄弟节点

$('.inner').after('<p>Test</p>');

4. 父节点

$('.inner').wrap('<div class="new"></div>');
$('.inner').wrapAll('<div class="new"></div>');
$('.inner').wrapInner('<div class="new"></div>');

5. 复制/删除/替换节点

工具函数

$(':checkbox').map(function () {
    return this.id;
}).get().join(',');

$(':checkbox').map(function (index, node) {
    return node.id;
}).get().join(',');
$('li').slice(2).css('background-color', 'red');
$('li').slice(2, 4).css('background-color', 'green');
$('li').slice(-2, -1).css('background-color', 'blue');

通用工具

$.each([52, 97], function (index, value) {
    console.log((index + ' : ' + value));
});
$.map([0, 1, 2], function (index, n) {
    return n + 4;
});
$.map([0, 1, 2], function (n) {
    return n > 0 ? n + 1 : null;
});
$.map([0, 1, 2], function (n) {
    return [n, n + 1];
});

var dimensions = {width: 10, height: 15, length: 20};
$.map(dimensions, function (value, key) {
    return value * 2;
});

var dimensions = {width: 10, height: 15, length: 20};
$.map(dimensions, function (value, key) {
    return key;
});
var object = $.extend({}, object1, object2);
var object = $.extend(true, {}, object1, object2);
$.merge([0, 1, 2], [2, 3, 4]);
$.grep([0, 1, 2], function (array, index) {
    return n > 0;
});//[1,2]
$.grep([0, 1, 2], function (array, index) {
    return n > 0;
}, true);//[0]
$.inArray(value, array [, fromIndex])
var xml = "<rss version='2.0'><channel><title>RSS Title</title></channel></rss>",
    xmlDoc = $.parseXML(xml),
    $xml = $(xmlDoc),
    $title = $xml.find("title");

上下文绑定

var o = {
    x: '123',
    f: function () {
        console.log(this.x)
    },
};
var go = function (f) {
    f()
};

o.f();// 123
go(o.f);// undefined
go($.proxy(o.f, o));//123
$.proxy(o, 'f')(); //123

当一个函数被传递之后,它就失去了原先的上下文。

把数据存到节点中

jQuery提供了一种机制,可以把节点作为数据存储的容器。

在内部实现上,jQuery会在指定节点添加一个内部标识,以此为key,把数据存在内部闭包的一个结构中。

事实上,jQuery的事件绑定机制也使用了这套数据接口。

$.data($('#data').get(0), 'test', '123');
$('#data').data('test', '456');

事件处理

1. 事件绑定

在 jQuery1.7之后,推荐统一使用on()来进行事件绑定。

$('#btn').on('click', function (eventObj) {
    console.log('Hello');
})

对于handler,它默认的上下文是触发事件的节点:

$('#btn').on('click', function (eventObj) {
    console.log(this);
})

使用$.proxy()可以随意控制上下文:

$('#btn').on('click',
    $.proxy(function (eventObj) {
        console.log(this.a);
    }, {a: 123})); // 123

event参数还支持通过:

- 以`.`分割的子名字
- 以空格分割的多个事件
$('#btn').on('click.my', (function (eventObj) {
            console.log('123');
        }
    )
);
var f = function () {
    $('#btn').off('click.my')
};

多个事件:

$('#btn').on('click.my click.other',
    (function (eventObj) {
            console.log('123');
        }
    )
);
var f = function () {
    $('#btn').off('click.my')
}

on()的另一种调用形式:

$('#btn').on({
    'click': function (eventObj) {
        console.log('click');
    },
    'mousemove': function (eventObj) {
        console.log('move');
    }
});

off()的使用方式与on()完全类似:

var f = function (eventObj) {
    console.log('Hello');
};
$('#btn').on('click', f);
$('#btn').off('click');

2. 事件触发

事件的触发有两种方式,一是使用预定的“事件函数”(.click().focus()),二是使用trigger()triggerHandler()

$('#btn').on('click', function (eventObj) {
    console.log("hello");
});
$('#btn').click();
$('#btn').trigger('click');

trigger()triggerHandler()不同之处在于前面是触发事件,而后者是执行绑定函数。

$('#btn').on('focus', function (event) {
    console.log("Hello");
});
$('#btn').triggerHandler('focus');

trigger()triggerHandler()也用于触发自定义事件。

$('#btn').on('my', function (event) {
    console.log("Hello");
});
$('#btn').triggerHandler('my');

trigger()triggerHandler()触发事件时,可以带上参数:

$('#btn').on('my', function (event) {
    console.log(obj);
});
$('#btn').trigger('my', {a: 123});

3. 事件类型

行为事件:

键盘事件:

鼠标事件:

页面事件:

4. 事件对象

如果一个绑定函数最后返回了false,则默认是event.preventDefault()event.stopPropagation()行为。

AJAX

1. 请求与回调

jQuery的AJAX,核心的请求处理函数只有一个,就是$.ajax(),然后就是一个简单的上层函数。

$.ajax() 的基本使用形式是:

jQuey.ajax(settings) settings是一个对象,里面包含了所有的配置项。

2. 请求的状态

对于全局的所有AJAX请求而言,可以在任意节点上绑定到全局任意AJAX请求的每一个事件:

$('#loading').ajaxStart(function () {
    $(this).show();
});

3. 工具函数

$('form').submit(function () {
    alert($(this).serialize());
    return false;
});
$('form').submit(function () {
    alert($(this).serializeArray());
    return false;
});

泛化回调

1. Deferred

var obj = $.Deferred(function (a) {

});
obj.done(function () {
    console.log("1");
});
obj.done(function () {
    console.log("2");
});
obj.resolve();

总的来说:jQuery的Deferred对象有三个状态:donefailprocess

- `process` 只能先于其他两个状态先被激发。
- `done`和`fail`互斥,只能激发一个。
- `process`可以被重复激发,而`done`和`fail`只能激发一次。

然后,jQuery提供了一些函数用于添加回调,激发状态等。

如果一个Deferred已经被激发,则新添加的对应的函数会被立即执行。

jQuery还提供了一个jQuery.when()的回调管理函数,可以用于方便地管理多个事件并发的情况。

var defer = $.ajax({
    url: 'test.html',
    dataType: 'json'
});
defer.done(function (data) {
    console.log(data);
});

done()做的事和使用success()定义是一样的。

当我们需要完成,像“请求A和请求B都完成时,执行函数”之类的需求时,使用$.when()就可以了。

var defer_1 = $.ajax({
    url: 'json.html',
    dataType: 'json'
});
var defer_2 = $.ajax({
    url: 'jsonp.html',
    dataType: 'jsonp'
});
var new_defer = $.when(defer_1, defer_2);
new_defer.done(function () {
    console.log("hello");
});

$.when()中的Deferred,只要有一个是fail,则整体结果为fail

Deferred的回调函数的执行顺序与它们的添加顺序一致。

这里特别注意一点,就是done/fail/alwaysthen的返回值的区别。从功能上看,它们都可以添加回调函数,但是,方法的返回值是不同的。前组的返回值是原来的那个defer对象,而then返回的是一个新的defer对象。

then返回新的defer这种形式,可以用于方便地实现异步函数的链式调用。

defer.done(function () {
    return $.ajax({
        url: '/json',
        dataType: 'json',
        success: function () {
            console.log("inner");
        }
    })
}).done(function () {
    console.log("hello");
});

等同于是调用了两次 defer.done, defer.done ,注册的两次回调函数依次被执行后,看到的输出是:helloinner

这是两次 defer.done 的结果,第一个回调函数返回了一个新的 defer 没任何作用。

如果换成 then 方法:defer.then(function () {...});

它跟两次 defer.done 是不同的。 new_defer 会在 inner 那里的 defer 被触发时再被触发,所以输出结果是:innerhello

更一般地来说 then 的行为,就是前面的注册函数的返回值,会作为后面注册函数的参数值:

var defer = $.ajax({
    url: '/json',
    dataType: 'json'
});
defer.then(function (res) {
    console.log(res);
    return 1;
}).then(function (res) {
    console.log(res);
    return 2;
}).then(function (res) {
    console.log(res);
});

上面代码的输入结果是:ajax response12

2. Callbacks

事实上,Deferred机制,只是在Callbacks机制的上层进行了一层简单封装。Callbacks对象才是真正的jQuery中定义的原始的回调管理机制。

var obj = $.Callbacks();
obj.add(function () {
    console.log("1");
});
obj.add(function () {
    console.log("2");
});
obj.fire();

Callbacks对象的初始化支持一组控制参数:

CallbackS的控制方法: