jQuery封装

130 阅读4分钟

闭包和链式操作

链式风格也叫jQuery风格

  • window.jQuery() 是我们提供的全局函数。

特殊函数 jQuery

  • jQuery(选择器) 用于获取对应的元素

  • 但它却不返回这些元素

  • 相反,它返回一个对象,称为 jQuery 构造出来的对象,这个对象是api。

  • 这个对象可以操作对应的元素

1.png

  • 解析:给我一个className,我会遍历elements,每个elements都会添加一个className,它不return elements,而是return 可以操作elements的api。

  • addClass(){console.log(elements)} 等价于 "addClass" : function(){console.log(elements)} 意思为 api 有一个 key 为 addClass ,value 为 function,function的值为 console.log 为 elements 。

  • 这里用到了闭包,函数访问外部的变量

2.png

  • 闭包: jQuery精髓1(核心思想): jQuery提供一个函数,这个函数接受一个选择器(CSS的选择器),通过这个选择器会获取到一些元素,但不会返回给你这些元素,返回一个对象,这个对象里有些方法(函数),这些函数来操作你的元素。用闭包去维持这个elements,只要这个函数不死,这个elements就不会死。因为这个函数在访问elements,是不能被删掉的,所以系统不敢删掉这个elements。

  • 链式操作: 精髓2:函数它能猜到你在调用addClass的时候,肯定是通过你得到的api,所以才会大胆的return this, return this的目的是它希望 .前面的东西做为.addClass 的返回值。这样的话,api从前面传到后面,又可以.addClass,api又从前面传到后面,又可以.addClass,从前面传到后面。

  • 省略后的代码

3.png

jQuery是构造函数吗?

4.png

  • 口头约定:jQuery 对象代指 jQuery 函数构造出来的对象,jQuery 对象不是说 「jQuery 这个对象」

实现find函数和$div.find返回新的Api对象

  • jQuery('#xxx') 返回值并不是元素,而是一个 api 对象

  • jQuery('#xxx').find('.red') 查找 #xxx 里的 .red 元素

  • jQuery('#xxx').parent() 获取爸爸

  • jQuery('#xxx').children() 获取儿子

  • jQuery('#xxx').siblings() 获取兄弟

  • jQuery('#xxx').index() 获取排行老几(从0开始)

  • jQuery('#xxx').next() 获取弟弟

  • jQuery('#xxx').prev() 获取哥哥

  • jQuery('.red').each(fn) 遍历并对每个元素执行 fn

7.png

6.png

  • 操作分三步:第一步得到新的Api,由jQuery构造出来(不能用之前的api);第二步jQuery不能只接受选择器,还要接受数组;第三步声明elements 的值为空,根据选择器是'string'还是Array,分别赋予不同的值,然后再去返回一个Api去操作。 (返回的不是array)

  • 如果发现改变对象,就再构造一个jQuery对象,jQuery Api 。

实现end函数

  • 使得结果集可以后退一步:
$('div')

   .find('h3')

   .eq(2)

   .html('Hello')

   **.end() //退回到选中所有的h3元素的那一步**

   .eq(0) //选中第一个h3元素

   .html('World'); //将它的内容改为World

8.png

  • 注意:find(selector)里面的array.oldApi=this中的this是指旧的api;end (){return this.oldApi}中的this是指新的api。

实现each,parent,children

each

9.png

  • 注意:这里的this就是api 对象

parent

10.png

  • 注意:-1表示还没有push;这里的this就是api对象;直接return array没有可操作性,所以封装一个操作数组的对象,也就是jQuery(array)。

11.png

  • 注意:这里的print(){conlose.log(elements)} 中的elements就是对应的元素们。

children

12.png

  • 注意: array.push(...node.children)array.push(node.children[0],node.children[1],node.children[2]...) 的缩写,因为不知道children有几个,所以就发明了array.push(...node.children)的写法。

jQuery其他的设置

window.$ = window.jQuery

  • 代码中所有 $ 开头的变量都是 jQuery 对象

13.png

  • 注意: window.$ = window.jQuery = function(selectorOrArray)先执行右边 window.jQuery = function(selectorOrArray),再得到的window.jQuery的值赋值给window.$

  • DOM对象只能使用DOM API ,如querySelector ,appendChild;如果是DOM API 就在div前面加上el。

  • jQuery对象只能使用jQUery的API , 如find , each;如果是jQuery的API 就在div前面加上$。

14.png

jQuery核心思想

选择网页元素

  • jQuery的基本设计思想和主要用法,就是 "选择某个网页元素,然后对其进行某种操作"

  • 使用jQuery的第一步,往往就是将一个选择表达式,放进构造函数jQuery()(简写为$),然后得到被选中的元素。

选择表达式可以是[CSS选择器]

  • $(document) //选择整个文档对象

  • $('#myId') //选择ID为myId的网页元素

  • $('div.myClass') // 选择class为myClass的div元素

  • $('input[name=first]') // 选择name属性等于first的input元素

jQuery[特有的表达式]

  • $('a:first') //选择网页中第一个a元素

* $('tr:odd') //选择表格的奇数行

* $('#myForm :input') // 选择表单中的input元素

* $('div:visible') //选择可见的div元素

* $('div:gt(2)') // 选择所有的div元素,除了前三个

* $('div:animated') // 选择当前处于动画状态的div元素

改变结果集

jQuery设计思想之二,就是提供各种强大的[过滤器],对结果集进行筛选,缩小选择结果。

  • $('div').has('p'); // 选择包含p元素的div元素

  • $('div').not('.myClass'); //选择class不等于myClass的div元素

  • $('div').filter('.myClass'); //选择class等于myClass的div元素

  • $('div').first(); //选择第1个div元素

  • $('div').eq(5); //选择第6个div元素

链式操作

jQuery设计思想之三,就是最终选中网页元素以后,可以对它进行一系列操作,并且所有操作可以连接在一起,以链条的形式写出来,比如:

$('div').find('h3').eq(2).html('Hello');

分开来:

$('div') //找到div元素

   .find('h3') //选择其中的h3元素

   .eq(2) //选择第3个h3元素

   .html('Hello'); //将它的内容改为Hello

元素的操作:取值和赋值

jQuery设计思想之四,就是使用同一个函数,来完成取值(getter)和赋值(setter),即"取值器"与"赋值器"合一。到底是取值还是赋值,由函数的参数决定。

$('h1').html(); //html()没有参数,表示取出h1的值

$('h1').html('Hello'); //html()有参数Hello,表示对h1进行赋值
  • 常见的取值和赋值函数如下:
.html() 取出或设置html内容

.text() 取出或设置text内容

.attr() 取出或设置某个属性的值

.width() 取出或设置某个元素的宽度

.height() 取出或设置某个元素的高度

.val() 取出某个表单元素的值
  • 注意:如果结果集包含多个元素,那么赋值的时候,将对其中所有的元素赋值;取值的时候,则是只取出第一个元素的值(.text()例外,它取出所有元素的text内容)。

元素的操作:移动

jQuery设计思想之五,就是提供两组方法,来操作元素在网页中的位置移动。一组方法是直接移动该元素,另一组方法是移动其他元素,使得目标元素达到我们想要的位置。

  1. 第一种方法是使用.insertAfter(),把div元素移动p元素后面:

$('div').insertAfter($('p'));

  1. 第二种方法是使用.after()),把p元素加到div元素前面:

$('p').after($('div'));

  • 注意:第一种方法返回div元素,第二种方法返回p元素。

使用这种模式的操作方法,一共有四对:

.insertAfter().after():在现存元素的外部,从后面插入元素

.insertBefore().before():在现存元素的外部,从前面插入元素

.appendTo().append():在现存元素的内部,从后面插入元素

.prependTo().prepend():在现存元素的内部,从前面插入元素

工具方法:不必选中元素,就可以直接使用这些方法。

  • $.trim() 去除字符串两端的空格。

  • $.each() 遍历一个数组或对象。

  • $.inArray() 返回一个值在数组中的索引位置。如果该值不在数组中,则返回-1。

  • $.grep() 返回数组中符合某种标准的元素。

  • $.extend() 将多个对象,合并到第一个对象。

  • $.makeArray() 将对象转化为数组。

  • $.type() 判断对象的类别(函数对象、日期对象、数组对象、正则对象等等)。

  • $.isArray() 判断某个参数是否为数组。

  • $.isEmptyObject() 判断某个对象是否为空(不含有任何属性)。

  • $.isFunction() 判断某个参数是否为函数。

  • $.isPlainObject() 判断某个参数是否为用"{}"或"new Object"建立的对象。

  • $.support() 判断浏览器是否支持某个特性。

  • $('#xxx') 返回值并不是元素,而是一个 api 对象

  • $('#xxx').find('.red') 查找 #xxx 里的 .red 元素

  • $('#xxx').parent() 获取爸爸

  • $('#xxx').children() 获取儿子

  • $('#xxx').siblings() 获取兄弟

  • $('#xxx').index() 获取排行老几(从0开始)

  • $('#xxx').next() 获取弟弟

  • $('#xxx').prev() 获取哥哥

  • $('.red').each(fn) 遍历并对每个元素执行 fn

  • $('<div><span>1</span></div>')

  • $(选择器),又可以传标签内容,这是 JS 的函数「重载」,一个函数可以接受不同的参数

  • $('<div><span>1</span></div>')返回值并不是新增的元素,而是 api 对象。$('<div><span>1</span></div>').appendTo(...),appendTo 可以把新增的元素放到另一个元素里。

15.png

16.png

  • $('body') 获取 document.body

  • $('body').append($('<div>1</div>')) 添加小儿子

  • $('body').append('<div>1</div>') 更方便

  • $('body').prepend(div或$div) 添加大儿子

  • $('#test').after(div 或 $div) 添个弟弟

  • $('#test').before(div 或 $div) 添个哥哥

  • $div.remove()

  • $div.empty() //清空元素内容(但是不删除该元素)

  • 删除元素使用.remove()和.detach()。两者的区别在于,前者不保留被删除元素的事件,后者保留,有利于重新插入文档时使用。

  • $div.text(?) 读写文本内容

  • $div.html(?) 读写 HTML 内容

  • $div.attr('title', ?) 读写属性

  • $div.css({color: 'red'}) 读写 style // $div.style 更好

  • $div.addClass('blue') / removeClass / hasClass

  • $div.on('click', fn)

  • $div.off('click', fn)

  • 注意:$div 可能对应了多个 div 元素

使用原型

使用原型

  • 把共用属性(函数)全都放到 $.prototype

  • $.fn = $.prototype // 名字太长不爽

  • 然后让 api.__ proto__ 指向 $.fn

17.png

  • jQuery fn = jQuery.prototype{...}

如何让函数访问elements的作用域

19.png

  • 注意:让elements出现在Api的身上,然后把所有共有属性对elements的独操作改成 this.elements(这里的this是api),再加上constructor:jQuery

jQuery的设计模式

jQuery 用到了哪些设计模式

  • 不用 new 的构造函数,这个模式没有专门的名字

  • $(支持多种参数),这个模式叫做重载

  • 用闭包隐藏细节,这个模式没有专门的名字

  • $div.text() 即可读也可写,getter / setter

  • $.fn$.prototype 的别名,这叫别名

  • jQuery 针对不同浏览器使用不同代码,这叫适配器