jq是一款伟大的,用原生js封装的,【操作DOM的类库】。他里面封装了大量的方法,基于这些方法我们可以快速的进行DOM操作和项目的开发

1.学习jq的方法

  • 看API文档 http://jquery.cuishifeng.cn/
  • 看相关书籍
  • 做案例
  • 学习jq的源码
    • 更好的掌握jq的应用
    • 让自己的js能力、封装组件和插件的能力得到进一步的提升

      2.jq的三个大的版本

      v1.xxx

      第一代版本的特点:大而全,方法是兼容所有浏览器的(包括IE6),主要应用于需要考虑兼容的PC端项目中

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源码剖析

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <script>
  10. // jq的最外层是一个自执行函数
  11. (function (global, factory) {
  12. "use strict" // 使用严格模式
  13. if (typeof module === "object" && typeof module.exports === "object") {
  14. // 支持CommonJs规范的执行这里,(比如在node.js里)
  15. // module.exports = global.document ?
  16. // factory(global, true) :
  17. // function (w) {
  18. // if (!w.document) {
  19. // throw new Error("jQuery requires a window with a document");
  20. // }
  21. // return factory(w);
  22. // };
  23. } else {
  24. // 走这里可以认为就是在浏览器里边运行
  25. // factory就是实参的函数,global就是window
  26. factory(global); // global--> window
  27. }
  28. }(typeof window !== "undefined" ? window : this, function (window, noGlobal) {
  29. var deletedIds = [];
  30. var slice = deletedIds.slice;
  31. var concat = deletedIds.concat;
  32. var push = deletedIds.push;
  33. var indexOf = deletedIds.indexOf;
  34. var class2type = {};
  35. var toString = class2type.toString;
  36. var hasOwn = class2type.hasOwnProperty;
  37. var support = {};
  38. var version = "1.11.3";
  39. var jQuery = function (selector, context) {
  40. return new jQuery.fn.init(selector, context);
  41. };
  42. // jq的是一个类,并且给jq加了一个私有属性,期属性值也是当前jq类的原型
  43. jQuery.fn = jQuery.prototype = {
  44. jquery: version, // jq的版本
  45. constructor: jQuery, // 给jq的原型进行重定向,手动补全constructor
  46. toArray: function () { // jq的类数组转数组方法
  47. return slice.call(this);
  48. },
  49. get: function (num) { // 获取jq实例里的某一个具体的元素,或者将jq实例转为数组
  50. return num != null ?
  51. // Return just the one element from the set
  52. (num < 0 ? this[num + this.length] : this[num]) :
  53. // Return all the elements in a clean array
  54. slice.call(this);
  55. },
  56. each: function (callback, args) { // each方法在jQ的类的原型上和Jq自己身上都存在
  57. return jQuery.each(this, callback, args);
  58. },
  59. };
  60. var init = jQuery.fn.init = function (selector, context) {
  61. // 这里的代码就是jq的元素选择器
  62. }
  63. init.prototype = jQuery.fn;
  64. if (typeof noGlobal === "undefined") {
  65. window.jQuery = window.$ = jQuery;
  66. }
  67. }));
  68. // 检测当前对象是数组还是类数组
  69. // function isArraylike(obj) {
  70. // var length = "length" in obj && obj.length,
  71. // type = jQuery.type(obj);
  72. // if (type === "function" || jQuery.isWindow(obj)) {
  73. // return false;
  74. // }
  75. // if (obj.nodeType === 1 && length) {
  76. // return true;
  77. // }
  78. // return type === "array" || length === 0 ||
  79. // typeof length === "number" && length > 0 && (length - 1) in obj;
  80. // }
  81. // jq上的方法放到了两个位置上,一部分在jq类的原型上,一部分在jq自己身上
  82. // $() // 返回的是init的实例,但是init的原型是jquery的原型
  83. // 但是这块大家有没有疑惑,为什么他不直接 new jquery()呢,只是人家的更加简洁的写法而已
  84. // function Fn(){
  85. // return new Fn();
  86. // }
  87. // Fn()
  88. /*
  89. 基于$执行创建出来的是jQ的实例,就可以调取jQ原型上的方法
  90. 1、创建出来的实例是一个类数组
  91. 2、$执行时支持传递三种不同的格式
  92. $('.box') jq选择器
  93. $('<div></div>') 创建jq实例版的元素
  94. $(js原生元素) 转化成jq的实例版的元素(因为只有这样才可以调用jq原型上的方法)
  95. 原生js中的方法或属性和jq的方法或者不能相互调用
  96. 把jq对象转化成js原生对象,直接获取即可(也可以用jq的get方法)
  97. eq(index)==> eq也是通过索引来获取某个元素,但是获取的是jq的实例
  98. 3、$(function(){}) 等待页面中的DOM结构加载完成再执行函数,等价于 $(document).ready(function(){})
  99. */
  100. // $(selector)selector==> 支持三种格式
  101. // 传字符串 --> $('.box') jq选择器
  102. // 传字符串 --> $('<div></div>')
  103. // var
  104. // _jQuery = window.jQuery,
  105. // _$ = window.$;
  106. // 转让$和jQuery的使用权
  107. // jQuery.noConflict = function (deep) {
  108. // if (window.$ === jQuery) {
  109. // window.$ = _$;
  110. // }
  111. // if (deep && window.jQuery === jQuery) {
  112. // window.jQuery = _jQuery;
  113. // }
  114. // return jQuery;
  115. // };
  116. //-------------------------------------------------------------------
  117. // extend()
  118. $.extend({}) // 向jq中继续扩展方法,这种写法,是吧方法扩展到jQ的对象上,一般是为了给类库增加更多的方法
  119. $.fn.extend(true,{}); // 这种是扩展到jQ的原型上,让jq的实例去调用
  120. $().extend()
  121. // 大家注意这个布尔值如果不穿或者传false,如果你写的方法名和jq内会的冲突了,以jq的为主不会覆盖,但是如果布尔值是true,那以你写的为主
  122. $.extend(true,{
  123. queryUrlParams:function(){
  124. }
  125. })
  126. $.queryUrlParams('xxxxxxx');
  127. /*
  128. 分三部分去讲
  129. 1、jq的基础实现原理
  130. 2、jq里的一些简单的方法 get each eq jq的选择器
  131. 3、jq的noConflict extend ready(类似于onload)
  132. */
  133. </script>
  134. </body>
  135. </html>

5.jq选项卡

  1. <div id="box">
  2. <ul id="navList">
  3. <li class="active">一</li>
  4. <li>二</li>
  5. <li>三</li>
  6. </ul>
  7. <div class="active">我们是一</div>
  8. <div>我们是二</div>
  9. <div>我们是三</div>
  10. </div>
  11. <script src="./jquery-1.11.3.js"></script>
  12. <script>
  13. // let navList = document.querySelectorAll('#navList li');
  14. // let tabList = document.querySelectorAll('#box div');
  15. // for (let i = 0; i < navList.length; i++) {
  16. // navList[i].onclick = function(){
  17. // selected(i)
  18. // }
  19. // }
  20. // function selected(index){
  21. // for (var i = 0; i < navList.length; i++) {
  22. // navList[i].className = '';
  23. // tabList[i].className = '';
  24. // }
  25. // navList[index].className = 'active';
  26. // tabList[index].className = 'active';
  27. // }
  28. // $('#navList li').each(function(index,item){
  29. // console.log(item)
  30. // $(item).click(function(){console.log(1)})
  31. // })
  32. // // index:获取当前元素在所有兄弟中的位置的索引
  33. // $('#navList li').click(function(){
  34. // console.log($(this).index()) // 获取当前this所在位置的索引
  35. // $(this).addClass('active').siblings().removeClass('active');
  36. // $('#box div').eq($(this).index()).addClass('active').siblings().removeClass('active');
  37. // })
  38. $('#navList li').click(function () {
  39. $(this).addClass('active').siblings().removeClass('active').parent().nextAll().eq($(this).index()).addClass('active').siblings('div').removeClass('active');
  40. });
  41. </script>

6.购物车

  1. <script>
  2. /*
  3. 1、获取所有的i标签
  4. 2、给每一个i标签绑定点击事件
  5. */
  6. let $btns = $('.list i');
  7. let $infoEms = $('.info em'); // 获取下半部分里的所有em元素
  8. let $ems = $('.list em'); // 获取上部分所有的em元素
  9. let $strongs = $('.list strong');
  10. $btns.click(function(){
  11. let index = $(this).index() // 拿到当前元素在自己所有的兄弟姐妹中的索引
  12. let $count = $(this).siblings('em'); // 获取显示数量的em元素
  13. let num = parseFloat($count.html()); // 获取当前em的内容
  14. let $strong = $count.siblings('span').find('strong'); // 获取素有的strong元素
  15. let price = parseFloat($strong.eq(0).html()) // 获取当前商品的单价
  16. // console.log($strong)
  17. if(index == 0) {
  18. // 点击的减号
  19. num-- ;
  20. num<0?num = 0:null; //
  21. }
  22. else {
  23. // 点击的加
  24. num++
  25. };
  26. $count.html(num); // 把数量设置回去
  27. $strong.eq(1).html(num*price+'元'); // 把小计设置回去
  28. computed();
  29. })
  30. function computed(){
  31. let allCount = 0; // 初始化一个累加数量的变量
  32. let allPrice = 0; // 初始化一个累加总计的变量
  33. let ary = [0]; // 初始化一个存储商品单价的数组
  34. // 循环上半部分所有的em元素
  35. $ems.each(function(index,item){
  36. // 把每一个em元素的内容累加到allCount
  37. allCount+=parseFloat($(item).html());
  38. });
  39. $strongs.each(function(index,item){
  40. // 如果strong元素的索引为偶数那就是单价那个元素,如果是奇数那就是小计那个元素
  41. if(index%2===1){
  42. // 把所有的小计元素的内容累加到allPrice里
  43. allPrice+=parseFloat($(item).html())
  44. }
  45. else {
  46. // 如果当前单价对应的小计不为位0,那就把单价push到ary数组里,用来一会在里面获取最大的单价
  47. if(parseFloat($(item).next('strong').html()) !== 0){
  48. ary.push(parseFloat($(item).html()))
  49. }
  50. }
  51. })
  52. // 以下三局就是把内容重新放回页面的元素中
  53. $infoEms.eq(0).html(allCount);
  54. $infoEms.eq(1).html(allPrice);
  55. $infoEms.eq(2).html(Math.max(...ary));
  56. /*
  57. 1、获取所有的strong标签
  58. 2、循环所有的strong标签
  59. 3、判断当前strong的索引,如果是奇数,那就是小计的那个标签
  60. */
  61. }
  62. </script>