jq是一款伟大的,用原生js封装的,【操作DOM的类库】。他里面封装了大量的方法,基于这些方法我们可以快速的进行DOM操作和项目的开发
1.学习jq的方法
- 看API文档 http://jquery.cuishifeng.cn/
- 看相关书籍
- 做案例
- 学习jq的源码
v2.xxx
主要是为移动端的开发准备的,不在兼容低版本浏览器(例如:IE8及以下),配合出现的还有 jQuery mobile等UI库。但是,第二代版本在移动端方面的处理不如 Zepto.js
v3.xxx
也不再兼容IE低版本浏览器了,它从性能等方面都要比之前的强,但是生不逢时,此时正好是angular / vue / react这种框架崛起的时代,大家已经不再基于操作DOM的思想开发了,JQ也就慢慢退出舞台了
3.jq常用的方法
请参考jq的官方API文档: http://jquery.cuishifeng.cn/
4.jq源码剖析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// jq的最外层是一个自执行函数
(function (global, factory) {
"use strict" // 使用严格模式
if (typeof module === "object" && typeof module.exports === "object") {
// 支持CommonJs规范的执行这里,(比如在node.js里)
// module.exports = global.document ?
// factory(global, true) :
// function (w) {
// if (!w.document) {
// throw new Error("jQuery requires a window with a document");
// }
// return factory(w);
// };
} else {
// 走这里可以认为就是在浏览器里边运行
// factory就是实参的函数,global就是window
factory(global); // global--> window
}
}(typeof window !== "undefined" ? window : this, function (window, noGlobal) {
var deletedIds = [];
var slice = deletedIds.slice;
var concat = deletedIds.concat;
var push = deletedIds.push;
var indexOf = deletedIds.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var support = {};
var version = "1.11.3";
var jQuery = function (selector, context) {
return new jQuery.fn.init(selector, context);
};
// jq的是一个类,并且给jq加了一个私有属性,期属性值也是当前jq类的原型
jQuery.fn = jQuery.prototype = {
jquery: version, // jq的版本
constructor: jQuery, // 给jq的原型进行重定向,手动补全constructor
toArray: function () { // jq的类数组转数组方法
return slice.call(this);
},
get: function (num) { // 获取jq实例里的某一个具体的元素,或者将jq实例转为数组
return num != null ?
// Return just the one element from the set
(num < 0 ? this[num + this.length] : this[num]) :
// Return all the elements in a clean array
slice.call(this);
},
each: function (callback, args) { // each方法在jQ的类的原型上和Jq自己身上都存在
return jQuery.each(this, callback, args);
},
};
var init = jQuery.fn.init = function (selector, context) {
// 这里的代码就是jq的元素选择器
}
init.prototype = jQuery.fn;
if (typeof noGlobal === "undefined") {
window.jQuery = window.$ = jQuery;
}
}));
// 检测当前对象是数组还是类数组
// function isArraylike(obj) {
// var length = "length" in obj && obj.length,
// type = jQuery.type(obj);
// if (type === "function" || jQuery.isWindow(obj)) {
// return false;
// }
// if (obj.nodeType === 1 && length) {
// return true;
// }
// return type === "array" || length === 0 ||
// typeof length === "number" && length > 0 && (length - 1) in obj;
// }
// jq上的方法放到了两个位置上,一部分在jq类的原型上,一部分在jq自己身上
// $() // 返回的是init的实例,但是init的原型是jquery的原型
// 但是这块大家有没有疑惑,为什么他不直接 new jquery()呢,只是人家的更加简洁的写法而已
// function Fn(){
// return new Fn();
// }
// Fn()
/*
基于$执行创建出来的是jQ的实例,就可以调取jQ原型上的方法
1、创建出来的实例是一个类数组
2、$执行时支持传递三种不同的格式
$('.box') jq选择器
$('<div></div>') 创建jq实例版的元素
$(js原生元素) 转化成jq的实例版的元素(因为只有这样才可以调用jq原型上的方法)
原生js中的方法或属性和jq的方法或者不能相互调用
把jq对象转化成js原生对象,直接获取即可(也可以用jq的get方法)
eq(index)==> eq也是通过索引来获取某个元素,但是获取的是jq的实例
3、$(function(){}) 等待页面中的DOM结构加载完成再执行函数,等价于 $(document).ready(function(){})
*/
// $(selector)selector==> 支持三种格式
// 传字符串 --> $('.box') jq选择器
// 传字符串 --> $('<div></div>')
// var
// _jQuery = window.jQuery,
// _$ = window.$;
// 转让$和jQuery的使用权
// jQuery.noConflict = function (deep) {
// if (window.$ === jQuery) {
// window.$ = _$;
// }
// if (deep && window.jQuery === jQuery) {
// window.jQuery = _jQuery;
// }
// return jQuery;
// };
//-------------------------------------------------------------------
// extend()
$.extend({}) // 向jq中继续扩展方法,这种写法,是吧方法扩展到jQ的对象上,一般是为了给类库增加更多的方法
$.fn.extend(true,{}); // 这种是扩展到jQ的原型上,让jq的实例去调用
$().extend()
// 大家注意这个布尔值如果不穿或者传false,如果你写的方法名和jq内会的冲突了,以jq的为主不会覆盖,但是如果布尔值是true,那以你写的为主
$.extend(true,{
queryUrlParams:function(){
}
})
$.queryUrlParams('xxxxxxx');
/*
分三部分去讲
1、jq的基础实现原理
2、jq里的一些简单的方法 get each eq jq的选择器
3、jq的noConflict extend ready(类似于onload)
*/
</script>
</body>
</html>
5.jq选项卡
<div id="box">
<ul id="navList">
<li class="active">一</li>
<li>二</li>
<li>三</li>
</ul>
<div class="active">我们是一</div>
<div>我们是二</div>
<div>我们是三</div>
</div>
<script src="./jquery-1.11.3.js"></script>
<script>
// let navList = document.querySelectorAll('#navList li');
// let tabList = document.querySelectorAll('#box div');
// for (let i = 0; i < navList.length; i++) {
// navList[i].onclick = function(){
// selected(i)
// }
// }
// function selected(index){
// for (var i = 0; i < navList.length; i++) {
// navList[i].className = '';
// tabList[i].className = '';
// }
// navList[index].className = 'active';
// tabList[index].className = 'active';
// }
// $('#navList li').each(function(index,item){
// console.log(item)
// $(item).click(function(){console.log(1)})
// })
// // index:获取当前元素在所有兄弟中的位置的索引
// $('#navList li').click(function(){
// console.log($(this).index()) // 获取当前this所在位置的索引
// $(this).addClass('active').siblings().removeClass('active');
// $('#box div').eq($(this).index()).addClass('active').siblings().removeClass('active');
// })
$('#navList li').click(function () {
$(this).addClass('active').siblings().removeClass('active').parent().nextAll().eq($(this).index()).addClass('active').siblings('div').removeClass('active');
});
</script>
6.购物车
<script>
/*
1、获取所有的i标签
2、给每一个i标签绑定点击事件
*/
let $btns = $('.list i');
let $infoEms = $('.info em'); // 获取下半部分里的所有em元素
let $ems = $('.list em'); // 获取上部分所有的em元素
let $strongs = $('.list strong');
$btns.click(function(){
let index = $(this).index() // 拿到当前元素在自己所有的兄弟姐妹中的索引
let $count = $(this).siblings('em'); // 获取显示数量的em元素
let num = parseFloat($count.html()); // 获取当前em的内容
let $strong = $count.siblings('span').find('strong'); // 获取素有的strong元素
let price = parseFloat($strong.eq(0).html()) // 获取当前商品的单价
// console.log($strong)
if(index == 0) {
// 点击的减号
num-- ;
num<0?num = 0:null; //
}
else {
// 点击的加
num++
};
$count.html(num); // 把数量设置回去
$strong.eq(1).html(num*price+'元'); // 把小计设置回去
computed();
})
function computed(){
let allCount = 0; // 初始化一个累加数量的变量
let allPrice = 0; // 初始化一个累加总计的变量
let ary = [0]; // 初始化一个存储商品单价的数组
// 循环上半部分所有的em元素
$ems.each(function(index,item){
// 把每一个em元素的内容累加到allCount
allCount+=parseFloat($(item).html());
});
$strongs.each(function(index,item){
// 如果strong元素的索引为偶数那就是单价那个元素,如果是奇数那就是小计那个元素
if(index%2===1){
// 把所有的小计元素的内容累加到allPrice里
allPrice+=parseFloat($(item).html())
}
else {
// 如果当前单价对应的小计不为位0,那就把单价push到ary数组里,用来一会在里面获取最大的单价
if(parseFloat($(item).next('strong').html()) !== 0){
ary.push(parseFloat($(item).html()))
}
}
})
// 以下三局就是把内容重新放回页面的元素中
$infoEms.eq(0).html(allCount);
$infoEms.eq(1).html(allPrice);
$infoEms.eq(2).html(Math.max(...ary));
/*
1、获取所有的strong标签
2、循环所有的strong标签
3、判断当前strong的索引,如果是奇数,那就是小计的那个标签
*/
}
</script>