JavaScritp面向对象思想实现jQuery核心功能

面向对象实现JQ库核心功能

整体框架

有个类,类里面有方法 然后进行实例化,秦段页面进行直接调用

class Jq {
constructor(arg) {

}
// 点击事件
click(fn) {
fn()
}
}
function $(arg) {
return new Jq(arg);
}

因为jquery可以进行多种传递方式所以需要在 constructor里面进行获取是那种传递方式

constructor(arg, root) {
if (typeof arg === "function") {
// dom 结构加载完毕执行代码
this.ready(arg)
} else if (typeof arg === "string") {
// 传入id 或者 class
let ele = document.querySelectorAll(arg);
this.addELement(ele)
} else {
//传入的是js原生节点
if (typeof arg.length == 'undefined') {
//一个对象节点
this[0] = arg
this.length = 1
} else {
//多个对象节点
this.addELement(arg)

}
}

}

eq()

jquery有eq方法 而eq方法后还可以调用其他方法

如:

$("div").eq(0).click(function () {})

这里就需要考虑原型链的问题了

基本面向对象实现链式操作

let = {
click(){
console.log("click")
return this
}
css(){
console.log("css")
return this
}
}
obj.click().css()

而在这个封装里面我们返回的不是this 了而是个对象

// 获取指定一个
eq(index) {
return new Jq(this[index], this)
}

end()

获取上一次的操作节点

如:

$('div').eq(1).end()

这个结果就是 获取 $('div') 的结果

如果直接获取第一个没有上一次的节点那么就需要给 undefined

我们需要在 constructor 内进行处理

constructor(arg, root) {
// 是否有上一次操作的节点
if (typeof root === 'undefined') {
this['prevObject'] = [document]
} else {
this['prevObject'] = root
}
}j

而这个 root 是在eq()` 当中传递过来的

// 获取指定一个
eq(index) {
return new Jq(this[index], this)
}

返回 this 当前的 如果没有返回那么就是 undefined

//获取上一次操作的节点
end() {
return this['prevObject']
}

css处理

可能获取的参数

1.获取css 的样式

$('.box1').css('background')

2.设置css样式 两个参数

$('.box1').css('background','red')

3.设置css样式 对象

$('.box1').css({'background':'red','margin':'10px'})

那么可以根据这几个方式 进行编写css的方法

css(...arg) {
if (arg.length === 1) {
if (typeof arg[0] === 'string') {
if (arg[0] in $.cssHooks) {
return $.cssHooks[arg[0]].get(this[0]);
}
// 字符串
return this.getStyle(this[0], arg[0])
} else {
//传入的对象
for (let i = 0; i < this.length; i++) {
for (let j in arg[0]) {
this.setStyle(this[i], j, arg[0][j])
}
}
}
} else {
// 多个参数
for (let i = 0; i < this.length; i++) {
this.setStyle(this[i], arg[0], arg[1]);
}
}
return this;
}

获取样式

// 获取样式
getStyle(ele, styleName) {
return window.getComputedStyle(ele, null)[styleName]
}

设置样式

这个特别注意下 $.cssNumber

// 设置样式
setStyle(ele, styleName, styleValue) {
if (typeof styleValue === 'number' && !(styleName in $.cssNumber)) {
styleValue = styleValue + "px"
}
if (styleName in $.cssHooks) {
$.cssHooks[styleName].set(ele, styleValue);
} else {
ele.style[styleName] = styleValue;
}
}

这个是出来这个css 值是否为 number 是否加上px的判断

那么有的需要加上px 有的不需要加上就需要用上这些参数了

判断是否在这里面如果不在 就需要加上px

$.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
}

完整js代码

class Jq {
constructor(arg, root) {
// 是否有上一次操作的节点
if (typeof root === 'undefined') {
this['prevObject'] = [document]
} else {
this['prevObject'] = root
}

if (typeof arg === "function") {
// dom 结构加载完毕执行代码
this.ready(arg)
} else if (typeof arg === "string") {
// 传入id 或者 class
let ele = document.querySelectorAll(arg);
this.addELement(ele)
} else {
//传入的是js原生节点
if (typeof arg.length == 'undefined') {
//一个对象节点
this[0] = arg
this.length = 1
} else {
//多个对象节点
this.addELement(arg)

}
}

}
// 获取指定一个
eq(index) {
return new Jq(this[index], this)
}
get(index) {
return this[index]
}
//获取上一次操作的节点
end() {
return this['prevObject']
}
// 处理多个节点
addELement(ele) {
ele.forEach((el, index) => {
this[index] = el;
})
this.length = ele.length
}
// 处理方法直接
ready(arg) {
window.addEventListener("DOMContentLoade", arg, false)
}
// 点击事件
click(fn) {
// fn()
for (let i = 0; i < this.length; i++) {
this[i].addEventListener("click", fn, false)
}
}
on(eventName, fn) {
let reg = /\s+/g;
eventName = eventName.replace(reg, " ")
let arr = eventName.split(" ")
for (let i = 0; i < this.length; i++) {
for (let j = 0; j < arr.length; j++) {
this[i].addEventListener(arr[j], fn, false)
}
}

}
css(...arg) {
if (arg.length === 1) {
if (typeof arg[0] === 'string') {
if (arg[0] in $.cssHooks) {
return $.cssHooks[arg[0]].get(this[0]);
}
// 字符串
return this.getStyle(this[0], arg[0])
} else {
//传入的对象
for (let i = 0; i < this.length; i++) {
for (let j in arg[0]) {
this.setStyle(this[i], j, arg[0][j])
}
}
}
} else {
// 多个参数
for (let i = 0; i < this.length; i++) {
this.setStyle(this[i], arg[0], arg[1]);
}
}
return this;
}
// 获取样式
getStyle(ele, styleName) {
return window.getComputedStyle(ele, null)[styleName]
}
// 设置样式
setStyle(ele, styleName, styleValue) {
if (typeof styleValue === 'number' && !(styleName in $.cssNumber)) {
styleValue = styleValue + "px"
}
if (styleName in $.cssHooks) {
$.cssHooks[styleName].set(ele, styleValue);
} else {
ele.style[styleName] = styleValue;
}
}
}

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 = {};
上一篇

JavaScript面向对象思想实现贪吃蛇小游戏