jQuery 是一个着重简化 DOM 操作,AJAX 调用和事件(en-US)处理的 JavaScript 库。

使用流程:

  1. 选取元素,返回对象,对其操作。
  2. 对象中有各种方法操作,针对所有被选取的元素。
  3. 多个连续的操作可以用“链式”实现。

jQuery的核心思想:
1.提供一个jQuery函数,函数接收一个选择器 jQuery(selector)
2.根据选择器得到一些元素,但不会返回这些元素,而是返回一个对象(jQuery构造出来的对象,称为API)
3.这个对象有各种方法(函数),这些函数可以操作这些元素
[

](https://blog.csdn.net/qq_40282016/article/details/116263519)

jQuery风格/链式风格的DOM库

前置知识:


jQuery对象

window.jQuery() 是全局函数

  • jQuery是个函数,可以构造出一个API对象;
  • jQuery不是常规意义上的构造函数,却有构造函数的某些特点,因为构造出了一个api对象;
  • 而真正意义上的构造函数需要结合new操作符才行
  • jQuery对象 全称jQuery构造出来的对象口头约定)类比:Object对象表示Object构造出来的对象

链式风格/jQuery风格

  • 闭包
  • 链式

链式调用

实现基础:$(selector)返回的是一个可以操作被选中元素的api对象

  1. $('div')
  2. .find('h3')
  3. .addClass('red')
  4. .text('hi 我是新加的内容');
  5. // 找到所有的div元素,在所有的div元素里找到h3标签,给h3标签增加'red'类,并且替换文本内容

常用API

首先明确:
基于DOM树的结构,一个子节点只能有一个父节点,
故无则“增”,有则“改”,而“改”在既有前提下也是“移”

  1.   $('<li class="new">new list item</li>'); //创建li
  2.   $('ul').append('<li>list item</li>'); //将li添加到ul中

  1. $div.remove()
  2. $div.empty()

改(读&写)

  1. $div.text(?) //读写文本内容
  2. $div.html(?) //读写HTML内容
  3. $div.css({'color': 'red'}) // 读写style属性,注意此处函数名为 css
  4. $div.on('click', fn)
  5. $div.off('click', fn)
  6. $div.addClass() //向匹配的元素添加指定的类名。
  7. $div.attr() //设置或返回匹配元素的属性和值。
  8. $div.hasClass() //检查匹配的元素是否拥有指定的类。
  9. $div.html() //设置或返回匹配的元素集合中的 HTML 内容。
  10. $div.removeAttr() //从所有匹配的元素中移除指定的属性。
  11. $div.removeClass() //从所有匹配的元素中删除全部或者指定的类。
  12. $div.toggleClass() //从匹配的元素中添加或删除一个类。
  13. $div.val() //设置或返回匹配元素的值。

另:在对元素属性进行操作时建议使用JSON形式控制样式

  1. $("#mybtn").css({
  2. width:200,
  3. height:"200",
  4. "background-color":"red"
  5. })

如何移动元素

  1. .insertAfter()和.after() //在现存元素的外部,从后面插入元素
  2. .insertBefore()和.before() //在现存元素的外部,从前面插入元素
  3. .appendTo()和.append() //在现存元素的内部,从后面插入元素
  4. .prependTo()和.prepend() //在现存元素的内部,从前面插入元素

  1. $('#xxx') //返回值并不是元素们,而是一个api对象
  2. $('#xxx').find('.red') //查找#xxx里的.red元素
  3. $('#xxx').parent() //获取爸爸
  4. $('#xxx').children() //获取儿子
  5. $('#xxx').siblings() //获取兄弟姐妹
  6. $('#xxx').index() //获取排序索引
  7. $('#xxx').next() //获取弟弟妹妹
  8. $('#xxx').each() //遍历并对每个元素执行fn

DOM对象和jQuery对象


DOM对象:
只能使用DOM 的API,如querySelector 、appendChild
jquery对象:
只能使用jQuery 的API,如 find、each

  1. const div1 = document.querySelector('.test') //直接操作DOM
  2. const div2 = $('.test') //使用jquery

注意:
使用jQuery中声明的变量div2 实际上是jQuery 构造的api对象
写成:const $div = $('div#test')
故:以 $开头的变量,都是jQuery对象,即jQuery构造出来的对象

对象命名风格

DOM对象:普通对象只需原形或者加前缀-el ;如:let eldiv1或div1
jQuery对象:加前缀-$ ;如:let $div2

jQuery原型

  • 把共有属性(函数)全部放到jQuery原型上
  • $.fn = $.prototype { //各种方法 }
  • api.proto指向$.fn
  • 原型内的函数变量elements访问不到,则需要用api作为桥梁,在函数内返回值后添加this去访问api
  • 原型内补constructor:jQuery,因为重新开辟了一块空间地址会影响之前constructor

手写一个jQuery风格的DOM库

  1. window.$ = window.jQuery = function(selectorOrArrayOrTemplate) {
  2. let elements;
  3. //先判断要获取的元素们是属于 选择器内 的还是 数组内的
  4. if (typeof selectorOrArrayOrTemplate === "string") {
  5. if (selectorOrArrayOrTemplate[0] === "<") {
  6. // 创建 div
  7. elements = [createElement(selectorOrArrayOrTemplate)];
  8. } else {
  9. // 查找 div
  10. elements = document.querySelectorAll(selectorOrArrayOrTemplate);
  11. }
  12. } else if (selectorOrArrayOrTemplate instanceof Array) {
  13. elements = selectorOrArrayOrTemplate;
  14. }
  15. function createElement(string) { //对象风格的DOM库在 创建元素时 的用法:
  16. const container = document.createElement("template");
  17. container.innerHTML = string.trim();
  18. return container.content.firstChild;
  19. }
  20. // jQuery方法:api 可以操作elements
  21. const api = Object.create(jQuery.prototype)// 等价于:const api = {__proto__: jQuery.prototype}
  22. Object.assign(api, {
  23. elements: elements,
  24. oldApi: selectorOrArrayOrTemplate.oldApi
  25. })
  26. // 等价于:api.elements = elements ;api.oldApi = selectorOrArrayOrTemplate.oldApi
  27. return api
  28. };
  29. //jquery原型
  30. jQuery.fn = jQuery.prototype = {
  31. constructor: jQuery, //原型内补充构造者constructor:jQuery,因为重新开辟了一块空间地址会影响之前constructor
  32. jquery: true,
  33. //增、删、改、查
  34. get(index) {
  35. return this.elements[index]; //由于原型内的函数变量访问不到前面区块内的elements变量,则需要用api作为桥梁,在函数内返回值后添加this去访问api
  36. },
  37. appendTo(node) {
  38. if (node instanceof Element) {
  39. this.each(el => node.appendChild(el));
  40. } else if (node.jquery === true) {
  41. this.each(el => node.get(0).appendChild(el));
  42. }
  43. },
  44. append(children) {
  45. if (children instanceof Element) {
  46. this.get(0).appendChild(children);
  47. } else if (children instanceof HTMLCollection) {
  48. for (let i = 0; i < children.length; i++) {
  49. this.get(0).appendChild(children[i]);
  50. }
  51. } else if (children.jquery === true) {
  52. children.each(node => this.get(0).appendChild(node));
  53. }
  54. },
  55. find(selector) {
  56. let array = [];
  57. for (let i = 0; i < this.elements.length; i++) {
  58. const elements2 = Array.from(this.elements[i].querySelectorAll(selector));
  59. array = array.concat(this.elements2);
  60. }
  61. array.oldApi = this; // this 就是 旧 api
  62. return jQuery(array);
  63. },
  64. each(fn) {
  65. for (let i = 0; i < this.elements.length; i++) {
  66. fn.call(null, this.elements[i], i);
  67. }
  68. return this;
  69. },
  70. parent() {
  71. const array = [];
  72. this.each(node => {
  73. if (array.indexOf(node.parentNode) === -1) {
  74. array.push(node.parentNode);
  75. }
  76. });
  77. return jQuery(array);
  78. },
  79. children() {
  80. const array = [];
  81. this.each(node => {
  82. if (array.indexOf(node.parentNode) === -1) {
  83. array.push(...node.children);
  84. }
  85. });
  86. return jQuery(array);
  87. },
  88. print() {
  89. console.log(this.elements);
  90. },
  91. // 闭包:函数访问外部的变量
  92. addClass(className) {
  93. for (let i = 0; i < this.elements.length; i++) {
  94. const element = this.elements[i];
  95. element.classList.add(className);
  96. }
  97. return this;
  98. },
  99. end() {
  100. return this.oldApi; // this 就是新 api
  101. }
  102. };