链式风格
也叫 jQuery 风格
- window.jQuery() 是我们提供的全局函数
命名风格
下面的代码令人误解
- const div = $('div#test')
- 我们会误以为 div 是一个 DOM
- 实际上 div 是 jQuery 构造的 api 对象
可以改成这样
- const div=('div#test')
- $div.appendChild 不存在,因为它不是 jQuery 对象
- $div.find 存在, 因为它是 jQuery 对象
特殊函数 jQuery
- jQuery(选择器) 用于获取对应的元素
- 但它却不返回这些元素
- 相反,它返回一个对象,称为 jQuery构造出来的对象
- 这个对象可以操作对应的元素
jQuery对象 代指 jQuery函数构造出来的对象
增
- $('<div><span>1</span></div>') 创建 div
- .appendTo(document.body) 插入到 body 中
删
- $div.remove()
- $div.empty()
改
- $div.text(?) 读写文本内容
- $div.html(?) 读写HTML内容
- $div.attr('titile', ?) 读写属性
- $div.css({color: 'red'}) 读写 style
- $div.addClass('blue')
- $div.on('click', fn)
- $div.off('click', fn)
- $div 大部分时候对应了多个 div 元素
查
- 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
jQuery 的设计模式
jQuery 用到了那些设计模式
- 不用 new 的构造函数, 这个模式没有专门的名字
- $(支持多种参数), 这个模式叫做重载
- 用闭包隐藏细节, 这个模式没有专门的名字
- $div.text() 即可读也可以写, getter / setter
- .fn是.prototype 的别名
- jQuery 针对不同浏览器使用不同代码, 这叫适配器
window.$ = window.jQuery = function (selectorOrArray) {
let elements
if (typeof selectorOrArray === 'string') {
elements = document.querySelectorAll(selectorOrArray)
} else if (selectorOrArray instanceof Array) {
elements = selectorOrArray
}
const api = Object.create(jQuery.prototype)
Object.assign(api, {
elements: elements,
oldApi: selectorOrArray.oldApi
})
return api
};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
jQuery: true,
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(elements2)
}
array.oldApi = this
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.children) === -1) {
array.push(...node.children)
}
})
return jQuery(array)
},
addClass(className) {
for (let i = 0; i < this.elements.length; i++) {
this.elements[i].classList.add(className)
}
return this
},
print() {
console.log(this.elements)
},
end() {
return this.oldApi
},
}