> 获取页面中元素的方法
document.getElementById()
context.getElementsByTagName()
context.getElementsByClassName() // 在 IE6-8 下不兼容
document.getElementsByName() // 在 IE 中只对表单元素的 name 起作用
document.body
document.documentElement
// 在 IE6-8 下不兼容,通过这个方法获取的节点集合不存在 DOM 映射
context.querySelector / context.querySelectorAll
描述节点和节点之间关系的属性(在标准浏览器中会把空格和换行当做文本节点处理)
childNodes
children 在 IE6-8 下获取的结果和标准浏览器获取的结果不一致
parentNode
previousSibling / previousElementSibling
nextSibling / nextElementSibling
lastChild / lastElementChild
firstChild / firstElementChild
自己写一个 类似 children 的兼容的方法
\ 判断是否需要兼容处理
\ 自己处理的返回的是一个数组,直接用 children 返回的是一个类数组
\ 元素节点 nodeType
===1
\ for( var i=0, len = nodeList.length; i<len; i++ )
\ if( /MSIE (6|7|8)/i.
test(navigator.userAgent
) )
\ ary = Array.prototype.slice.call(curEle.children)
\ 增加要求: 获取指定元素的子元素 传指定元素参数
var utils = (function(){ // 工具集
var flag = 'getComputedStyle' in window; // 判断
return {
xxx: function(){...}
}
})();
// 惰性思想:
// 有多个属性方法在IE 6-8 下不兼容,可以定义一个变量 flag 判断,
// 在后面的判断中,只要判断 flag 就可以了
function getChild(obj , tagName ){
var res = []; // 数组
if( /MSID (6|7|8)/.test(window.navigator.userAgent)){
//先获取所有节点,再根据 nodeType = 1 选出元素节点
var temp = obj.childNodes;
for( var i=0; len=temp.length, i<len; i++){
if( 1 === temp[i].nodeType){ // 类型判断
res[res.length] = temp[i];
}
}
temp = null; // 置空
} else {
// res = obj.children; // 这里得到不是数组
res = Array.prototype.slice.call(obj.children);
}
// 二次筛选
if( typeof tagName === 'string'){ // 传入的参数类型
for( var k=0; k<res.length; k++ ){ // for 循环写法的区别
if(tagName.toLowerCase() !== res[k].nodeName.toLowerCase()){ // 小写
res.splice(k,1); // 删除不符合要求的项
k--;
}
}
}
return res;
}
// 再考虑多传一个元素,查找指定子元素
console.log(getChild(document.body,'p').length);
工具集:
在自执行函数的私有作用域中定义函数 getChildNodes
在 return 中添加 getChildNodes: getChildNodes, …
> 获取兄弟元素节点
获取上一个元素节点 prev
// 获取元素上一个兄弟节点
// 兼容,标准浏览器直接返回,ie6-8 判断类型再返回
function prev(ele){
if(flag){
return ele.previousElementSibling;
}
var pre = ele.previousSibling;
while(pre && pre.nodeType !== 1){
pre = pre.previousSibling;
}
return pre;
}
获取前面所有的兄弟节点
// 获取前面所有兄弟节点
function prevAll(ele){
var ary = [];
var pre = this.prev(ele); // this
while(ele){
ary.unshift(pre); // 从第一个插入
pre = this.prev(pre);
}
return ary;
}
// 获取元素前一个元素和后一个元素
function sibling(ele){
var pre = this.prev(ele);
var nex = this.next(ele);
var ary = [];
pre ? ary.push(pre) : null;
nex ? ary.push(nex) : null;
return ary;
}
// 获取元素所有元素节点
function siblings(ele){
return this.prevAll(ele).concat(this.nextAll(ele));
}
// 获取元素下标
function index(ele){
return this.prevAll(ele).length;
}
// 获取元素的第一个子元素
function firstChild(ele){
var res = this.getChildNodes(ele);
return res.length > 0 ? res[0] : null;
}
// 获取元素最后一个子元素
function lastChild(ele){
var res = this.getChildNodes(ele);
return res.length >0 ? res[res.length] : null;
}
插入元素
// 向容器元素的最前面插入元素方法
function prepend(newEle, container){
var fir = this.firstChild(container);
if(fir){
container.insertBefore(newEle, fir); // 在第一个元素的前面插入
return;
}
container.appendChild(newEle);
}
// 向指定元素的后面插入元素
function insertAfter(newEle,oldEle){
var nex = this.next(oldEle); // 元素的后一个节点
if(nex){ // 如果存在后一个节点
oldEle.parentNode.insertBefore(newEle,nex);
return;
}
oldEle.parentNode.appendChild(newEle);
}
操作元素的样式类
// 验证当前元素是否包含 className 这个样式类
function hasClass(curEle, cName){
var reg = new RegExp('(^| +)'+cName +'( +|&)');
return reg.test(curEle.className);
}
// 添加 样式类
function addClass(curEle, cName){
var classAry = cName.split(/ +/g); // 用正则 可能有多个空格
for(var i=0; i<classAry.length; i++){
if(!hasClass(curEle,classAry[i])){ // 不存在
curEle.className += classAry[i];
}
}
}
删除某个样式类
如上代码,在 for 循环中,判断存在要删除的类型,再操作
var reg = new RegExp("(^| +)"+ classAry[i] + "( +|$)","g"); //
curEle.className = curEle.className.replace(reg, " "); // 用空格替换
删除首尾空格
" c a b ".replace(/(^ +| +$)/g, '')
getElementsByClassName 的兼容处理
// context: 获取元素的上下文,如果不传这个参数的话,默认为 document
function _getElementsByClassName(cName, context) {
context = context || document;
if(flag){ // 标准浏览器 这里返回的是一个类数组集合
return context.getElementsByClassName(cName);
}
var res = [];
var classAry = cName.replace(/(^ +| +$)/g, "").split(/ +/g); // 去除首尾空格,拆成数组
// 获取指定上下文所有元素
var allEleAry = context.getElementsByTagName("*"); // 通配符
for(var i = 0; i < allEleAry.length; i++) {
for(var j = 0; j < classAry.length; j++) {
var hc = true;
if(!hasClass(allEleAry[i], classAry[j])) { // 要同时拥有传进来的所有的样式类
hc = false;
break;
}
if(hc) {
res.push(allEleAry[i]);
}
}
}
return res;
}
设置元素样式
在 JS 中设置元素样式,只能通过 curEle.style[attr]
= value 来设置行内样式
自定义一个设置元素的方法,考虑 单位问题、兼容性问题、float
function setCss(curEle, attr, value){
// 考虑要加单位的情况 注意后面的首字母大写
var reg = /^(width|height|top|bottom|left|right|((margin|padding)(Top|Bottom|Right|Left)?))$/; // 正则
if(reg.test(attr)){ // 从属性判断是否要加单位
if(!isNaN(value)){
console.log('单位');
value += 'px';
}
}
// 还可能 的兼容的问题 opacity
if('opacity' === attr){
curEle['style'][attr] = value;
curEle['style']['filter'] = 'alpha(opacity = '+ value*100 +')';
console.log('aa');
return;
}
// 在 JS 中设置 float 也要处理兼容
if('float'=== attr){
curEle['style']["cssFloat"] = value;
curEle['style']["styleFloat"] = value;
return;
}
curEle['style'][attr] = value;
}
setCss(oBox,"borderTop","2px solid #333"); // 使用
批量设置元素样式
function setGroupCss(curEle,options){
// 先判断第二个参数存在,还有值的类型
options= options|| 0;
if(Object.prototype.toString.call(options) !== '[object Object]'){
// 用 options.toString() 也可以
return;
}
for( var key in options){
if( options.hasOwnProperty(key)){ //
setCss(curEle,key,options[key]);
}
}
}
获取样式设置样式方法合并 以参数的个数及类型来判断要进行的操作
> 选项卡
css:
overflow: hidden;
清除子元素浮动对父级的影响
clear: both;
前一元素子元素浮动,给后一元素加 清除前面元素浮动对后面元素的影响
-webkit-user-select: none;
禁止用户选定
选项卡和内容页都是先设置 display: none; , 添加类名后才: display: block;
结构:
#tab > ul + div*3 div 是内容区域
ul > li *3 li 是选项卡
var tab = document.getElementById('tab');
var tabLiss = tab.getElementsByTagName('li'); // 所有的选项卡
var tabDivs = tab.getElementsByTagName("div"); // 所有的内容
for( var i=0; i<tabLiss.length; i++){
tabLiss[i].index = i; // 自定义变量
tabLiss[i].onclick = function(){
changeCt(this.index);
}
}
function changeCt(n){
for(var i=0; i<tabDivs.length; i++){
tabDivs[i].className = 'none'; // 修改类名
tabLiss[i].className = 'none';
}
tabDivs[n].className = 'selet';
tabLiss[n].className = 'selet';
}
也可以用闭包的方法解决
for( var i=0; i<tabLiss.length; i++){
+function(i){ // 形成一个私有的作用域
tabLiss[i].onclick = function(){
changeCt(i);
}
}(i);
}
for( var i=0; i<tabLiss.length; i++){
tabLiss[i].onclick = (function(i){
return function(){ // 这样也可以
changeCt(i);
}
})(i);
}
封装选项卡函数
选项卡结构相同,但个数可能不同,当前展示项也不同