jQuery 是一个着重简化 DOM 操作,AJAX 调用和事件(en-US)处理的 JavaScript 库。
使用流程:
- 选取元素,返回对象,对其操作。
- 对象中有各种方法操作,针对所有被选取的元素。
- 多个连续的操作可以用“链式”实现。
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对象
$('div')
.find('h3')
.addClass('red')
.text('hi 我是新加的内容');
// 找到所有的div元素,在所有的div元素里找到h3标签,给h3标签增加'red'类,并且替换文本内容
常用API
首先明确:
基于DOM树的结构,一个子节点只能有一个父节点,
故无则“增”,有则“改”,而“改”在既有前提下也是“移”
增
$('<li class="new">new list item</li>'); //创建li
$('ul').append('<li>list item</li>'); //将li添加到ul中
删
$div.remove()
$div.empty()
改(读&写)
$div.text(?) //读写文本内容
$div.html(?) //读写HTML内容
$div.css({'color': 'red'}) // 读写style属性,注意此处函数名为 css
$div.on('click', fn)
$div.off('click', fn)
$div.addClass() //向匹配的元素添加指定的类名。
$div.attr() //设置或返回匹配元素的属性和值。
$div.hasClass() //检查匹配的元素是否拥有指定的类。
$div.html() //设置或返回匹配的元素集合中的 HTML 内容。
$div.removeAttr() //从所有匹配的元素中移除指定的属性。
$div.removeClass() //从所有匹配的元素中删除全部或者指定的类。
$div.toggleClass() //从匹配的元素中添加或删除一个类。
$div.val() //设置或返回匹配元素的值。
另:在对元素属性进行操作时建议使用JSON形式控制样式
$("#mybtn").css({
width:200,
height:"200",
"background-color":"red"
})
如何移动元素
.insertAfter()和.after() //在现存元素的外部,从后面插入元素
.insertBefore()和.before() //在现存元素的外部,从前面插入元素
.appendTo()和.append() //在现存元素的内部,从后面插入元素
.prependTo()和.prepend() //在现存元素的内部,从前面插入元素
查
$('#xxx') //返回值并不是元素们,而是一个api对象
$('#xxx').find('.red') //查找#xxx里的.red元素
$('#xxx').parent() //获取爸爸
$('#xxx').children() //获取儿子
$('#xxx').siblings() //获取兄弟姐妹
$('#xxx').index() //获取排序索引
$('#xxx').next() //获取弟弟妹妹
$('#xxx').each() //遍历并对每个元素执行fn
DOM对象和jQuery对象
DOM对象:
只能使用DOM 的API,如querySelector 、appendChild
jquery对象:
只能使用jQuery 的API,如 find、each
const div1 = document.querySelector('.test') //直接操作DOM
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库
window.$ = 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) { //对象风格的DOM库在 创建元素时 的用法:
const container = document.createElement("template");
container.innerHTML = string.trim();
return container.content.firstChild;
}
// jQuery方法:api 可以操作elements
const api = Object.create(jQuery.prototype)// 等价于:const api = {__proto__: jQuery.prototype}
Object.assign(api, {
elements: elements,
oldApi: selectorOrArrayOrTemplate.oldApi
})
// 等价于:api.elements = elements ;api.oldApi = selectorOrArrayOrTemplate.oldApi
return api
};
//jquery原型
jQuery.fn = jQuery.prototype = {
constructor: jQuery, //原型内补充构造者constructor:jQuery,因为重新开辟了一块空间地址会影响之前constructor
jquery: true,
//增、删、改、查
get(index) {
return this.elements[index]; //由于原型内的函数变量访问不到前面区块内的elements变量,则需要用api作为桥梁,在函数内返回值后添加this去访问api
},
appendTo(node) {
if (node instanceof Element) {
this.each(el => node.appendChild(el));
} else if (node.jquery === true) {
this.each(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);
}
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 => {
if (array.indexOf(node.parentNode) === -1) {
array.push(...node.children);
}
});
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
}
};