闭包和链式操作
链式风格也叫jQuery风格
window.jQuery()是我们提供的全局函数。
特殊函数 jQuery
-
jQuery(选择器) 用于获取对应的元素
-
但它却不返回这些元素
-
相反,它返回一个对象,称为 jQuery 构造出来的对象,这个对象是api。
-
这个对象可以操作对应的元素
-
解析:给我一个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 。 -
这里用到了闭包,函数访问外部的变量
-
闭包: jQuery精髓1(核心思想): jQuery提供一个函数,这个函数接受一个选择器(CSS的选择器),通过这个选择器会获取到一些元素,但不会返回给你这些元素,返回一个对象,这个对象里有些方法(函数),这些函数来操作你的元素。用闭包去维持这个elements,只要这个函数不死,这个elements就不会死。因为这个函数在访问elements,是不能被删掉的,所以系统不敢删掉这个elements。
-
链式操作: 精髓2:函数它能猜到你在调用addClass的时候,肯定是通过你得到的api,所以才会大胆的return this, return this的目的是它希望
.前面的东西做为.addClass的返回值。这样的话,api从前面传到后面,又可以.addClass,api又从前面传到后面,又可以.addClass,从前面传到后面。 -
省略后的代码
jQuery是构造函数吗?
- 口头约定: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
-
操作分三步:第一步得到新的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
- 注意:find(selector)里面的
array.oldApi=this中的this是指旧的api;end (){return this.oldApi}中的this是指新的api。
实现each,parent,children
each
- 注意:这里的this就是api 对象
parent
- 注意:-1表示还没有push;这里的this就是api对象;直接return array没有可操作性,所以封装一个操作数组的对象,也就是jQuery(array)。
- 注意:这里的
print(){conlose.log(elements)}中的elements就是对应的元素们。
children
- 注意:
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 对象
-
注意:
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前面加上$。
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设计思想之五,就是提供两组方法,来操作元素在网页中的位置移动。一组方法是直接移动该元素,另一组方法是移动其他元素,使得目标元素达到我们想要的位置。
- 第一种方法是使用
.insertAfter(),把div元素移动p元素后面:
$('div').insertAfter($('p'));
- 第二种方法是使用.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 可以把新增的元素放到另一个元素里。
增
-
$('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
jQuery fn = jQuery.prototype{...}
如何让函数访问elements的作用域
- 注意:让elements出现在Api的身上,然后把所有共有属性对elements的独操作改成 this.elements(这里的this是api),再加上constructor:jQuery
jQuery的设计模式
jQuery 用到了哪些设计模式
-
不用 new 的构造函数,这个模式没有专门的名字
-
$(支持多种参数),这个模式叫做重载
-
用闭包隐藏细节,这个模式没有专门的名字
-
$div.text()即可读也可写,getter / setter -
$.fn是$.prototype的别名,这叫别名 -
jQuery 针对不同浏览器使用不同代码,这叫适配器