虽然现代前端已经是MVVM框架的天下,但是在jQuery中的一些设计模式和思想还是值得我们借鉴和学习的。本文主要分实现了一些开发中使用比较频繁的方法和函数。由于能力有限,如有不妥的地方还请多多指教。
class Jq {
constructor(arg, root) {
if (typeof root === 'undefined') {
this['prevObject'] = [document];
} else {
this['prevObject'] = root;
}
// $(function(){console.log('解决')})
if (typeof arg === 'function') {
this.ready(arg)
} else if (typeof arg === 'string') {
// console.log($('li'))
const ele = document.querySelectorAll(arg);
this.addELement(ele)
} else {
//传入js原生节点;
// console.dir(arg)
if (typeof arg.length === 'undefined') {
// 一个对象节点;
// $(document.querySelectorAll('#wrap'))
this[0] = arg;
this.length = 1;
} else {
// 多个对象节点
// $(document.querySelectorAll('ul li'))
this.addELement(arg);
}
}
}
// 返回上一次的prevObject
end() {
return this['prevObject']
}
// 注意链式调用
eq(index) {
return new Jq(this[index], this)
}
// 添加元素
addELement(ele) {
// 处理HtmlCollectionList
ele = Array.from(ele);
ele.forEach((el, i) => {
this[i] = el;
})
this.length = ele.length;
}
// dom结构加载完毕执行代码
ready(cb) {
window.addEventListener('DOMContentLoaded', cb, false)
}
// 注册点击事件
click(cb) {
for (let i = 0; i < this.length; i++) {
this[i].addEventListener("click", cb, false)
}
}
// on函数注册事件
on(eventSource, cb) {
const reg = /\s+/g;
eventSource = eventSource.replace(reg, ',');
const eventSourceArray = eventSource.split(',');
for (let i = 0, len = this.length; i < len; i++) {
for (let j = 0, length = eventSourceArray.length; j < length; j++) {
this[i].addEventListener(eventSourceArray[j], cb, false);
}
}
}
css(...arg) {
if (arg.length === 1) {
if (typeof arg[0] === 'string') {
if(arg[0] in $.cssHooks) {
// 只获取第一个
return $.cssHooks[arg[0]].get(this[0])
}
// css('background') 只获取this[0]的样式
return this.getStyle(this[0], arg[0])
} else {
// css({'width':'200px','height':'200px'}))
console.log(arg) // [{'width':'200px','height':'200px'}]
for (let i = 0, len = this.length; i < len; i++) {
for (let j in arg[0]) {
this.setStyle(this[i], j, arg[0][j])
}
}
}
} else {
console.log(arg) // ["width", "200px"]
for (let i = 0, len = this.length; i < len; i++) {
this.setStyle(this[i], arg[0], arg[1])
}
}
}
setStyle(ele, attr, value) {
// 处理需要加单位的属性
if (typeof value === 'number' && !(attr in $.cssNumber)) {
value = value + 'px';
}
// 增加cssHooks判断
if (attr in $.cssHooks) {
$.cssHooks[attr].set(ele, value)
} else {
ele.style[attr] = value
}
}
getStyle(ele, styleName) {
return window.getComputedStyle(ele, null)[styleName]
}
}
function $(arg) {
return new Jq(arg)
}
// 以下属性都不需要加单位
$.cssNumber = {
animationIterationCount: true,
columnCount: true,
fillOpacity: true,
flexGrow: true,
flexShrink: true,
fontWeight: true,
gridArea: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnStart: true,
gridRow: true,
gridRowEnd: true,
gridRowStart: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
widows: true,
zIndex: true,
zoom: true
}
// cssHooks
$.cssHooks = {}
以上只是自己看了源码之后的仿写,可能实现不是太优雅。