CSS选择器
id选择器;类选择器;元素节点选择器。改写成更简单的方式:$('#main .a p')这种形式
创建好的库:function Base(){};new出Base对象的方法:var $=function(){return new Base()}
思路:调用时:$('#main .a p').......之前函数$()没有传参,所以从参数入手。
如果参数以#或 . 开头,就把#或.后面的部分作为id或class传给获取Id和获取class的方法内。而此时获取Id的方法是不用直接调用的,所以不用返回Base对象。
分为一个选择器如$('#main')和多个选择器如$('#main .a p')
当参数是一个选择器时与参数是多个选择器时改写,获取节点的方法。
1 当参数是一个选择器时:
Base.js改写:
var $=function(args){ //传参 //这里写一个函数,调用时返回一个Base对象
return new Base(args);//传参
}
function Base(args){ //传参
this.elements=[]; //把获取的节点放在这里面
if(typeof args=='string') {
switch(args.charAt(0)){ //判断参数的第一个字符
case '#':
this.elements.push(this.getId(args.substring(1))); //第二个字符开始截取
break;
case '.':
this.elements=this.getClass(args.substring(1)); //因为获取class节点的方法返回的是节点数组所以用等于号替换
break;
default:
this.elements=this.getTagName(args);
}
}
}
2 当参数是多个选择器时
Base对象设想:$('#main .a p):父-子-子。用main里的.a取代main在用.a里的p取代前面的p
思路:每次将前面获取的节点或节点数组作为父节点存放在一个数组里,第一次父节点用document,根据父节点找到子节点存放在另一个数组里,每次都要将这个数组设为空,防止重复添加。所以创建两个数组。
Base对象:
function Base(args){
this.elements=[]; //创建属性数组 保存获取的节点数组,实例(私有)属性不要在原型里添加
if(typeof args=='string') {
//参数是多个选择器
if(args.indexOf(' ')!=-1) { //如果有空格
var elements=args.split(' '); //以空格为界限将字符串分割成数组
var childElements=[]; //存放临时节点的数组解决被覆盖的问题
var node=[]; //存放第一个节点,即父节点的数组
for(var i=0;i<elements.length;i++) { //elements是一个数组,要做循环
if(node.length==0)node.push(document); //如果node为空,就把document添加进去
switch(elements[i].charAt(0)){ //判断第一个字符
case '#':
childElements=[]; //创建个数组存放获取的节点
childElements.push(this.getId(elements[i].substring(1)));
node=childElements; //得到的节点放在node里作为父节点
break;
case '.':
childElements=[]; //重新初始化为空
for(var j=0;j<node.length;j++){ //因为不止一个
var temps=this.getClass(elements[i].substring(1),node[j]); //获取第一个节点下面的节点
for(var k=0;k<temps.length;k++){ //不止一个要做循环
childElements.push(temps[k]);
}
}
node=childElements;
break;
default:
childElements=[];
for(var j=0;j<node.length;j++){
var temps=this.getTagName(elements[i],node[j]);
for(var k=0;k<temps.length;k++){
childElements.push(temps[k]);
}
}
node=childElements;
}
}
this.elements=childElements; //目标节点传给属性数组
}else{
// 当只有一个选择器时:
switch(args.charAt(0)){ //参数的第一个字符
case '#':
this.elements.push(this.getId(args.substring(1))); //出第二个字符开始截取
break;
case '.':
this.elements=this.getClass(args.substring(1));
break;
default:
this.elements=this.getTagName(args);
}
}
}
}
更改获取节点的方法:
Base.prototype.getId=function(id){
return document.getElementById(id); //将节点存入数组中
}
//获取name节点数组的方法
Base.prototype.getName=function(name){
var name=document.getElementsByName(name);
for(var i=0;i<name.length;i++){ //这里相同节点不止一个所以要循环,节点长度不是数组长度
this.elements.push(name[i]) //每个节点都要添加进去
}
return this;
};
//获取元素节点数组的方法
Base.prototype.getTagName=function(tag,parentNode){
var node=null; //创建一个对象·
var temps=[];
if(parentNode!==undefined){
node=parentNode
}else{
node=document
}
var tags=node.getElementsByTagName(tag);
for(var i=0;i<tags.length;i++){
temps.push(tags[i]);
}
return temps;
};
// 通过class获取多个相同节点
Base.prototype.getClass=function(className,parentNode){
var node=null; //表明node是一个对象但没有赋值
var temps=[]; // 数组用来存储目标节点
if (parentNode!=undefined) { //parentNode是节点对象,undefined不用加引号
node=parentNode;
}else{
node=document;
}
var all=node.getElementsByTagName('*'); //获取所有的元素节点
for(var i=0;i<all.length;i++)
{
if(all[i].className==className){ //如果节点的class名等于参数的class
temps.push(all[i]);
}
}
return temps;
};
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>原生js封装库</title>
<link rel="stylesheet" type="text/css" href="demo.css">
<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="Base.js"></script>
</head>
<body>
<div id="main" style="color: red"><p style="color:red">段落1</p></div>
<div class="main" style="color: red"><p style="color:red">段落2</p></div>
</body>
</html>
demo.js调用:
window.οnlοad=function(){
$('#main p').css('color','blue');
$('.main p').css('color','blue')
}
图示: