简介:
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。jQuery兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等。
jQuery的语法是选取一个元素,并对其执行操作。
jQuery如何获取元素
使用jQuery的第一步,是将一个选择表达式,放进构造函数jQuery()(简写为$())。
$('#xxx')返回值不是元素,是一个api对象。
$(document) // 选择整个文档对象 $('#xxx').find('.red') //选择#xxx里的.red元素 $('p') // 选择所有p标签 $('#aa') // 选择ID为aa的元素 $('.bb') // 选择class为bb的元素 $('input[name=cc]') // 选择name属性等于cc的input元素 $('p.red,p.green') // 把<p class="red">和<p class="green">都选出来 $('.red').each(fn) //遍历并对每个元素执行fn
jQuery的链式操作
每一步的jQuery()操作,返回的都是jQuery对象,所以不同操作可以连在一起,这就是链式操作,允许我们在相同的元素上运行多条 jQuery 命令,一条接着另一条。
$("#p1").css("color","red").slideUp(2000).slideDown(2000); //选择"p1"元素,使其变为红色,然后向上滑动,再然后向下滑动
jQuery创建元素
创建新元素,只要把新元素直接传入jQuery的构造函数就行了。
$("<div id='test' class='aaron'>我是文本节点</div>")
如需删除元素和内容,一般可使用以下两个 jQuery 方法:
- remove() - 删除被选元素(及其子元素)
- empty() - 从被选元素中删除子元素
jQuery移动元素
外部插入:
- after() - 在被选元素之后插入内容。
- before() - 在被选元素之前插入内容。
内部插入:
- append() - 在被选元素内部的结尾插入内容
- prepend() - 在被选元素内部的开头插入内容
还有另一种方法,insertAfter(),insertBefore(),appendTo(),prependTo(),功能相同,插入内容和目标的位置相反。
jQuery修改元素的属性
常见的取值和赋值函数:
.html() 返回或设置html内容 .text() 返回或设置text内容 .val() 返回或设置某个表单元素的值 .attr() 返回或设置某个属性的值 .width() 返回或设置某个元素的宽度 .height() 返回或设置某个元素的高度
其他常用
addClass()
在元素中增加指定的类
removeClass()
在元素中删除指定的类
toggleClass()
检查元素中指定的类,如果不存在则添加类,如果已设置则删除
闭包:
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包developer.mozilla.org链式结构:
javascript的链式编程的核心就是return this
;
连接来自于:
千锋HTML5学院:javascript中的链式操作zhuanlan.zhihu.comjQuery代码:
window.jQuery = function(selectorOrArrayOrTemplate){
let elements
if(typeof selectorOrArrayOrTemplate === 'string'){
if(selectorOrArrayOrTemplate[0] === '<'){
// 创建 div
elements=[createElement(selectorOrArrayOrTemplate)]
}else{
// 查找 div
elements = document.querySelectorAll(selectorOrArrayOrTemplate)
}
}else if(selectorOrArrayOrTemplate instanceof Array){
elements = selectorOrArrayOrTemplate
}
function createElement(string){
const container = document.createElement("template");
container.innerHTML = string.trim();
return container.content.firstChild;
}
// api 可以操作elements
return {
jquery: true,
elements: elements,
get(index){//闭包因为get用到了他外面的element变量,
return elements[index]
},
appendTo(node){
if(node instanceof Element){
this.each(el => node.appendChild(el)) // 遍历 elements,对每个 el 进行 node.appendChild 操作
}else if(node.jquery === true){
this.each(el => node.get(0).appendChild(el)) // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el)) 操作
}
},
append(children){
if(children instanceof Element){
this.get(0).appendChild(children)
}else if(children instanceof HTMLCollection){
for(let i =0;i<children.length;i++){
this.get(0).appendChild(children[i])
}
}else if(children.jquery === true){
children.each(node => this.get(0).appendChild(node))
}
},
find(selector){
let array = []
for(let i =0;i<elements.length;i++){
const elements2 = Array.from(elements[i].querySelectorAll(selector))
array = array.concat(elements2)
}
array.oldApi = this // this 就是 旧 api
return jQuery(array)
},
each(fn){
for(let i=0; i<elements.length;i++){
fn.call(null, elements[i], i)//fn(elements[i],i)
}
return this
},
parent(){
const array = []
this.each((node)=>{
if(array.indexOf(node.parentNode) === -1){
array.push(node.parentNode)
}
})
return jQuery(array)
},
children(){
const array = []
this.each((node)=>{
// 上课的时候这段代码是复制的,复制错了,现已改正
array.push(...node.children)//...把每个节点分开
})
//const newApi = jQuery(array)
//return newApi
return jQuery(array)
},
print(){
console.log(elements)
},
// 闭包:函数访问外部的变量,访问函数只能使用函数访问
addClass(className){
for(let i=0;i<elements.length;i++){
const element = elements[i]
element.classList.add(className)
}
return this
},
oldApi: selectorOrArrayOrTemplate.oldApi,
end(){
return this.oldApi // this 就是新 api
},
}
}
window.$ = window.jQuery
闭包的好处:用户不可以直接操作element需要通过操作函数才能够操作element比如get(){}函数
main.js代码:
const $div = $('<div><span>1</span></div>')
const $childList = $('.child')
$('body').append($childList)
index.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>手写 jQuery</title>
</head>
<body>
<div class="test">
你好1
<div class="child">child1</div>
<div class="child">child2</div>
<div class="child">child3</div>
</div>
<div class="test">
你好2
<div class="child">child2</div>
<div class="child">child3</div>
</div>
<div class="test">
你好3
<div class="child">child3</div>
</div>
<div id="container">
container
</div>
<script src="jquery.js"></script>
<script src="main.js"></script>
</body>
</html>
注意$div在大部分时候对应了多个div元素
querySelectorAll()
HTML DOM querySelectorAll() 方法www.runoob.comJavaScript HTML DOM 节点列表
JavaScript HTML DOM 节点列表www.runoob.comJavaScript HTML DOM 集合(Collection)
JavaScript HTML DOM 集合(Collection)www.runoob.comHTMLCollection 与 NodeList 的区别
- HTMLCollection 是 HTML 元素的集合。
- NodeList 是一个文档节点的集合。
- NodeList 与 HTMLCollection 有很多类似的地方。
- NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, ...) 来获取元素。
- NodeList 与 HTMLCollection 都有 length 属性。
- HTMLCollection 元素可以通过 name,id 或索引来获取。
- NodeList 只能通过索引来获取。
- 只有 NodeList 对象有包含属性节点和文本节点。
节点列表不是一个数组! 节点列表看起来可能是一个数组,但其实不是。 你可以像数组一样,使用索引来获取元素。 节点列表无法使用数组的方法: valueOf(), pop(), push(), 或 join() 。
后续:
使用原型
把共有的属性(函数)全部放到$.prototype
$.fn = $.prototype//名字太长不爽
然后让.api.__proto__指向$.fn
原理图:
后续代码:
window.jQuery = function(selectorOrArrayOrTemplate){
let elements
if(typeof selectorOrArrayOrTemplate === 'string'){
if(selectorOrArrayOrTemplate[0] === '<'){
// 创建 div
elements=[createElement(selectorOrArrayOrTemplate)]
}else{
// 查找 div
elements = document.querySelectorAll(selectorOrArrayOrTemplate)
}
}else if(selectorOrArrayOrTemplate instanceof Array){
elements = selectorOrArrayOrTemplate
}
function createElement(string){
const container = document.createElement("template");
container.innerHTML = string.trim();
return container.content.firstChild;
}
// api 可以操作elements
const api = Object.create(jQuery.prototype)//创建一个对象,这个对象的__proto__为括号里面的东西,相当于const api = {__proto__:jQuery.prototype}
Object.assign(api,{
elements:elements,//不可以再写api={}要不会覆盖前面的api
oldApi:selectorOrArrayOrTemplate.oldApi,
})//把后面的属性一个一个复制到前面去
// api.elements = elements//不可以再写api={}要不会覆盖前面的api
// api.oldApi = oldApi
return api
};//完成内存的节约
jQuery.fn = jQuery.prototype ={
jquery:true,
constructor:jQuery,
get(index){
return this.elements[index]//原先的代码是没有this的,那就获取不到element所以才加this
},
appendTo(node){
if(node instanceof Element){
this.each(el => node.appendChild(el)) // 遍历 elements,对每个 el 进行 node.appendChild 操作
}else if(node.jquery === true){
this.each(el => node.get(0).appendChild(el)) // 遍历 elements,对每个 el 进行 node.get(0).appendChild(el)) 操作
}
},
append(children){
if(children instanceof Element){
this.get(0).appendChild(children)
}else if(children instanceof HTMLCollection){
for(let i =0;i<children.length;i++){
this.get(0).appendChild(children[i])
}
}else if(children.jquery === true){
children.each(node => this.get(0).appendChild(node))
}
},
find(selector){
let array = []
for(let i =0;i<this.elements.length;i++){
const elements2 = Array.from(this.elements[i].querySelectorAll(selector))
array = array.concat(this.elements2)
}
array.oldApi = this // this 就是 旧 api
return jQuery(array)
},
each(fn){
for(let i=0; i<this.elements.length;i++){
fn.call(null,this.elements[i], i)//fn(elements[i],i)
}
return this
},
parent(){
const array = []
this.each((node)=>{
if(array.indexOf(node.parentNode) === -1){
array.push(node.parentNode)
}
})
return jQuery(array)
},
children(){
const array = []
this.each((node)=>{
// 上课的时候这段代码是复制的,复制错了,现已改正
array.push(...node.children)//...把每个节点分开
})
//const newApi = jQuery(array)
//return newApi
return jQuery(array)
},
print(){
console.log(this.elements)
},
// 闭包:函数访问外部的变量,访问函数只能使用函数访问
addClass(className){
for(let i=0;i<this.elements.length;i++){
const element = this.elements[i]
element.classList.add(className)
}
return this
},
end(){
return this.oldApi // this 就是新 api
},
}
window.$ = window.jQuery
运行结果:
设计模式:
JQuery 用到哪些设计模式
不用new的构造函数,这个模式没有专门的名字
$(支持多种参数),这个模式的叫做重载
用闭包隐藏细节,这个模式没有专门的名字
$div.text()即可读也可写,getter/setter
$.fn是$.prototype的别名,这叫做别名
JQuery针对不同浏览器使用不同的代码,这叫适配器
设计模式是啥?
给自己漂亮的代码写法取个名字,比如适配器模式
设计模式就是对通用代码取个名字
复习关于如何创建分支:
git branch//查看分支
git branch 分支名字
git checkout
git status
git add .
git commit -v/git commit -m "要写的注释"
git push origin 分支名字
完整代码:
1.master
2.branch是分支后续代码
Righthand5/JQuery-dome-2github.com大神博客:
jQuery设计思想 - 阮一峰的网络日志www.ruanyifeng.com