封装元素获取函数

封装元素获取函数

目的:JS中获取id名,类名,标签名的元素往往使用:
document.getElementbyId("idName");
document.getElementsbyTagName("tagName");
document.getElementsbyClassName("className");

在这里注意到Element在id处使用单数,其他两处是复数。可以理解为id在文档中是唯一的,而tag和class是一类,一个数组集合。

为了简化代码,使用函数封装方式,而不用重复去输入相同的代码。封装在一个js文件内,通过外部引用,实现重复利用,提高效率。

在这里我们通过:

<div id="only" class="all box">

来说明函数的使用。

达到的效果:
document.getElementById("only")
$("#only")
无需再输入过长的代码。而使用简单的“$”来调用。

在这里我们需要注意到通过getElementById(),括号内的内容为“only”,而通过$(),括号内内容为“#only”。

函数一:元素获取函数

function $(selector, context) {
	//select : 查找元素的选择器,可以为 id、类、元素选择器。context : 查询上下文对象
	context = context || document;
	if (selector.indexOf("#") === 0) // id 查询
		return document.getElementById(selector.slice(1));
	if (selector.indexOf(".") === 0) // 根据类名查询
		return getElementsByClass(selector.slice(1), context);
	return context.getElementsByTagName(selector);
}

在这里selector.indexOf("#") === 0还可以用如下方法代替:

		selector.slice(0,1) === "#"
		selector.charAt(0) === "#"
		selector[0] === "#"
		selector.startsWidth("#")

在这里我们通过获取$("#only")来理解这个函数。
对应$(selector,context),有:
selector =“#only”;
context = document ;

"#only"为一字符串,通过判断首字符是否为“#”号。返回
document.getElementById("only");
document.getElementById(selector.slice(1));
在这里selector.slice(1)表示截取字符串1号索引以后的字符串:

**“#only”**
	  01234
//01234表示每个字符在字符串中的索引

为什么这样表示呢?
之前提到,需要注意到通过getElementById(),括号内的内容为“only”,而通过$(),括号内内容为“#only”。
同理,可以去理解ClassName与TagName的调用获取。

$(".all")与$("div")

需要注意到的是在上一个函数中我们可以很好的获取到由id名或者标签名查找的元素。但是类名查找的元素在这里会遇到兼容问题。所以我们并不能直接使用getElementsByClassName()的方式来获取,而是需要引入一个新的函数来解决这个兼容问题。我们在上一个函数中对判断为类名的元素返回了这样一个值:
return getElementsByClass(selector.slice(1),context);

getElementsByClassName() 在IE9以下存在兼容问题。

函数二:解决getElementsByClassName() 兼容问题

function getElementsByClass(className, context) {
	context = context || document;
	if (context.getElementsByClassName)  // 支持使用 getElementsByClassName() 方法 
		return context.getElementsByClassName(className);
	/* 不支持使用 getElementsByClassName() */
	// 保存查找到的元素的数组结构
	var result = [];
	// 在查找上下文中查询出所有元素
	var tags = context.getElementsByTagName("*");
	// 遍历每一个元素,判断是否存在查询的类名
	for(var i in tags){
		// 获取当前遍历到元素的所有类名
		var classNames = tags[i].className.split(" ");
		var index = inArray(className, classNames);
		if (index !== -1) // 当前遍历到的元素标签是要查找的标签
			result.push(tags[i]);
	}
	// 返回查找结果的数组
	return result;
}

注意到“*”号了吗?为什么输入它我们就能找到所有元素呢?还记得css中的通配符吗?那么我们就明白了,为什么它代表了所有元素。

在这里,我们考虑在不支持getElementsByClassName()方法时,如何获取拥有className的元素?
首先,元素的className属性是有效的。我们只要将问题转化为,在所有元素中找到带有className的元素,这个问题就可以解决。
换句话说,当我们找到className===“all”的就ok。还要注意到的是,如之前所讲,通过类名,标签名找到的元素,是一个集合,或者可以说是一个数组。另外,一个元素的className也可能不只有一个。

<div id="only" class="all box">

多个类名,我们通过空格来分隔。

我们把一个className看成数组中的一项,那么这个数组可以看成是classNames,在这个例子中
className==“all”
classNames["all","box]

而想要获得classNames这个数组,就需要将字符串

“all box“
//分割为"all"与"box"
className.split(" ")

以上我们即可得到一个含有我们查找的类名的数组。通过函数二我们解决了getElementsByClassName()的兼容问题--IE9以下版本不支持。

然而在classNames数组内我们找到该数组中某个className时将使用到的indexOf()同样存在着兼容问题--IE8以下并不支持。
所以我们需要再次引入一个函数来解决indexOf()的兼容问题。

函数三:indexOf()的兼容问题

function inArray(value, array) {
	if (Array.prototype.indexOf) // 支持使用数组的 indexOf() 方法
		return array.indexOf(value);
	/* 不支持数组 indexOf() 方法 */
	for (var i = 0, len = array.length; i < len; i++) {
		if (array[i] === value) // 找到
			return i;
	}
	return -1; // 未找到
}

这个函数很简单,在没有indexOf的情况下像以前一样遍历数组,即可得到。

通过以上三个函数我们实行了获取元素的目的,因为兼容问题,我们不得不使用其他函数来解决这些问题。

现在,我们将三个函数放在同一个js文件下,就可以在下个html中直接引用,而不需要使用get的方法。美元你值得拥有
$("#d"),
$(".class"),
$("<标签>")

在获取到元素后如何获取或者设置css属性?
一般的我们使用$().style,这个方法的操作只会在html标签上实现。而无法获取到

<style type="text/css"></style>

内的属性。

函数四:解决css属性获取的兼容问题

obj.currentStyle与window.getComputedStyle

function css(element, attr, value) {
	// 获取
	if (typeof attr === "string" && !value)
		return window.getComputedStyle 
				? getComputedStyle(element)[attr]
				: element.currentStyle[attr];
	// 设置CSS样式
	if (typeof attr === "string" && value)
		element.style[attr] = value; // 使用内联样式设置CSS
	else if (typeof attr === "object") {
		for (var prop in attr) {
			element.style[prop] = attr[prop];
		}
	}
}

这个函数也比较简单,在这里就不再解释。
手敲完真的很累了,如果上面有什么错误的地方,还请指出。

原文地址:https://www.cnblogs.com/zhuxiaopeng/p/6838157.html