用 jQuery 封装 dom 有点难,适合多写几遍比较有感悟
所有的代码可以看我的 github 链接:github.com/huyiling111…
一、选择网页元素
jQuery 基本设计思想和主要用法,就是"就是选择某个网页元素,然后对其进行某种操作",设计模式是闭包隐藏细节
jQuery(选择器)用于获取对应的元素,但它不返回这些元素,而是 api 对象
下面一个简单的 jQuery 示例:
window.jQuery = function (selectorOrArrayOrTemplate) {
let elements;
if (typeof selectorOrArrayOrTemplate === "string") {
// 传进来的是选择器
elements = document.querySelectorAll(selectorOrArrayOrTemplate);
} else if (selectorOrArrayOrTemplate instanceof Array) {
// 传进来的是数组
elements = selectorOrArrayOrTemplate;
}
//elements就是要操作的元素或者节点
let api = {
// 下面这些函数可以操作 elements
find(selector) {
let array = [];
for (let i = 0; i < elements.length; i++) {
const elements2 = Array.from(elements[i].querySelectorAll(selector));
array.push(...elements2);
}
array.oldApi = this; // this 就是 旧 api
return jQuery(array);
//目的是返回新的api,新的elements值
},
appendTo(selector) {},
addClass(className) {},
end(className) {},
};
return api;
};
复制代码
**注意点:这里注意 typeof 一般用来判断返回的类型,比如 function,undefined,object,number,string,boolen
A instanceof B 用来判断 A 是不是 B 的实例,一般用于判断数组 **
二、链式调用
链式调用就是调用完函数,返回结果本身,然后用点语法调用下一个函数
另外还提供 end 方法,可以把结果集返回到 jQuery()调用返回的对象上,具体方法是:
传入一个 new api 对象为{oldapi:selectorOrArrayOrTemplate.oldapi},
在 end 方法里调用 this.oldapi ,这里指向的是selectorOrArrayOrTemplate.oldapi,也就是旧 api,具体实现看代码
let api = jquery(".text").find(".text1").addClass("red").end().addClass("blue");
let api2 = jquery(".text")
.each((div) => {
console.log(div);
})
.parent()
.print();
复制代码
此处应有分割线---------------------------------
return {oldapi: selectorOrArrayOrTemplate.oldapi,
find(selector) {
let array = []
for (let i = 0; i < elements.length; i++) {
let elements2 = Array.from(elements[i].querySelectorAll(selector))
array = array.concat(elements2)
}
array.oldapi = this
return jquery(array)
//目的是返回新的api,新的elements值
},
end() {
return this.oldapi
//返回到旧的的api
}}
复制代码
三、getter, setter 设计模式
这一段取自阮一峰博客:
jQuery 的设计思想之三就是使用同一个函数,来完成取值(getter)和赋值(setter)。到底是取值还是赋值,由函数的参数决定,这也是函数的重载。
$("h1").html(); //html()没有参数,表示取出h1的值
$("h1").html("Hello"); //html()有参数Hello,表示对h1进行赋值
复制代码
四、函数重载
函数重载就是一个函数可以传入不同类型的参数或者不同个数的参数,通过 if 语句和 arguments.length 判断
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();
console.log(container.innerHTML)
return container.content.firstChild;
}
复制代码
感想
所谓的设计模式只是对通用代码取个名字而已,日常写代码并不会遵循某个设计模式去写,而是写完后总结后发现用了某种设计模式。