实现一个jquery api
2019-06-20 本文已影响0人
lyp82nkl
jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
jQuery的核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。
jQuery本质
Query实质上是一个构造函数,该构造函数接受一个参数,jQuery通过这个参数利用原生API找到节点,之后返回一个方法对象,该方法对象上的方法对节点进行操作(方法使用了闭包)。
封装函数
<ul>
<li id="item1">选项1</li>
<li id="item2">选项2</li>
<li id="item3">选项3</li>
<li id="item4">选项4</li>
<li id="item5">选项5</li>
</ul>
1. 获取某一标签的全部兄弟元素
function getSiblings(node){
var allChildren = node.parentNode.children;
var arr = {
length: 0
}; //声明一个伪数组
for(var i =0;i<allChildren.length;i++){
if(allChildren[i] !== node){
arr[arr.length] = allChildren[i];
arr.length += 1;
}
}
return arr;
}
- DOM API 中的ParentNode.children属性,返回该节点的所有元素孩子。
- 返回节点父亲的所有孩子,然后遍历这个伪数组(children属性返回一个HTMLCollection实例,是一个伪数组),将不等于自身节点的其他节点放入一个空对象里。
- 声明的arr是一个伪数组,所以在遍历后不能使用数组的push方法,那么怎么把value放进数组呢?所以使用
array[array.length]=allChildren[i]
的方法
2. 给一个标签添加多个class
function addClass(node,classes){
for(var key in classes){
var value = classes[key];
if(value){
node.classList.add(key);
}else{
node.classList.remove(key)
}
}
}
以上两个函数,我们就可以直接对它们传参进行操作:
//得到除item2的全部兄弟元素
console.log(getSiblings(item2))
//给item2添加a,c两个类
addClass(item2,{a:true,b:false,c:true})
命名空间
我们获得了两个函数:getSiblings() , addClass() ,他们都是操纵节点,那我们能把他们联系起来吗?所以我们可以把他们放到一个库里,给它命名,这就叫命名空间。
window.ldom = {}
ldom.getSiblings(node)
ldom.addClass(node,classes)
var ldom = {}//声明一个名字为ldom的空间
ldom.getSiblings = function(node){
var allChildren = node.parentNode.children;
var arr = {
length: 0
};
for(var i =0;i<allChildren.length;i++){
if(allChildren[i] !== node){
arr[arr.length] = allChildren[i];
arr.length += 1;
}
}
return arr;
}
ldom.addClass = function(node,classes){
for(var key in classes){
var value = classes[key];
var method =value ? 'add' : 'remove';
node.classList[method](key);
}
}
console.log(ldom.getSiblings(item3));
ldom.addClass(item3,{a:true,b:false,c:true})
- 封装命名空间就是把所有封装的函数放入一个对象之中,通过调用对象的方法来调用封装的函数。 这样做有一个好处:不会污染全局变量
将 node 放在前面
node.getSiblings()
node.addClass()
方法一:扩展 Node 接口
直接在 Node.prototype 上加函数
Node.prototype.getSiblings=function(){
//this就是Node构造函数的实例对象,也就是节点
var allChildren = this.parentNode.children;
var arr = {
length: 0
};
for(var i =0;i<allChildren.length;i++){
if(allChildren[i] !== this){
arr[arr.length] = allChildren[i];
arr.length += 1;
}
}
return arr;
}
Node.prototype.addClass = function(classes){
for(var key in classes){
var value = classes[key];
var method =value ? 'add' : 'remove';
this.classList[method](key);
}
}
console.log(item3.getSiblings.call(item3)) //item3就是节点也就是Node的实例对象,它的下划线原型指向Node.prototype
item3.addClass.call(item3,{a:true,b:false,c:true})
- 直接在 Node 对象上添加封装函数,修改Node.protorype对象,在Node.prototype对象上新增方法。
- 缺点:修改 Node 对象的原型,可能无意识覆盖原生API
方法二:创建一个新的接口函数
window.Node2 = function(nodesSelect){
let nodes = {};
if(typeof nodesSelect === 'string'){
let temp = document.querySelectorAll(nodesSelect);//利用一个新的中间变量的到一个干净的伪数组(下划线原型直接执行Object)
for(let i =0;i<temp.length;i++){
nodes[i]= temp[i]
}
nodes.length = temp.length; }else if(nodesSelect instanceof Node){
nodes = { //这里之所以写成一个伪数组,是为了下面遍历它
0: nodesSelect,
length: 1
}
}
nodes.addClass = function(classes){
classes.forEach((value)=>{
for(let i = 0;i<nodes.length;i++){
nodes[i].classList.add(value)
}
})
}
//设置和获取文本内容
nodes.text = function(text){
if(text === undefined){
var texts = [];
for(let i =0;i<nodes.length;i++){
texts.push(nodes[i].textContent)
}
return texts;
}else{
for(let i =0;i<nodes.length;i++){
nodes[i].textContent = text;
}
}
}
return nodes;
}
var node2 = Node2(item3);
node2.addClass(['blue'])
- 优点不会覆盖原有的api,方便调用
将Node2 改个名字
function jQuery(node){
return {
element: node,
getSiblings: function(){
},
addClass: function(){
}
}
}
let node =document.getElementById('x')
let node2 =jQuery(node)
node2.getSiblings()
node2.addClass()
再给个缩写 alias
window.$ = jQuery
//$=jQuery也是可以的
这时就可以直接通过$('item2')来调用了,也就达到了类型jquery的效果
DOM对象跟jQuery对象相互转换
jQuery对象转换成DOM对象:
-
方式一:$(“#btn”)[0]
-
方式二:$(“#btn”).get(0)
DOM对象转换成jQuery对象:
-
$(document) -> 把DOM对象转成了jQuery对象
-
var btn = document.getElementById(“btn”);
-
btn -> $(btn);