DOM一些优化/简写与编程技巧
2018-03-06 23:15
155 查看
不需要查找可直接获得的节点
document.documentElement ->htmldocument.head ->head
document.body ->body
document.forms[id/i]每个表单元素 返回数组
添加和删除
优化方式:尽量减少操作DOM树的次数为什么要优化:
首先HTML的加载原理:
1、下载HTML
2、解析HTML为DOM树
3、将CSS解析为COM
4、他们结合为一个Rander Tree,渲染树用来描述所有的可见的DOM内容,并将CSSOM添加到节点上
这个时候,当修改DOM树任何一处的时候就需要重新渲染,会非常影响效率
那么,如何进行优化?
1、如果同时添加父元素和子元素的情况下:
那么,应该在内存中,先将所有子元素添加到父元素中,最后一次性的将父元素添加到DOM树
2、如果父元素已经在页面上,需要添加多个平级的子元素的情况下:
应该使用文档片段
什么是文档片段:
即内存中,临时保存多个平级子元素的虚拟父元素对象
何时使用:
需要添加多个平级子元素的时候
如何使用:
分3步:
1、创建文档片段:
var frag = document.createDocumentFragment();
2、将子元素添加到文档片段中
frag.appendChild(child)
3、将文档片段一次性添加到父元素上
parent.appendChild(frag);
强调:frag将子元素添加到页面后,frag自动释放
具体实例:<title>二级联动列表</title>
<meta charset="utf-8" />
<style>
.hide{ display: none; }
</style>
</head>
<body>
<select name="provs">
<option>—请选择—</option><!--0--> <!--技巧1:避免误操作-->
<option>北京市</option><!--1-->
<option>天津市</option>
<option>河北省</opti
4000
on>
</select>
<select name="cities" class="hide"><!--技巧2:用innerHTML情况两个标签之间的所有子元素-->
</select>
<script>
/*实现“省”和“市”的级联下拉列表*/
var cities=[
[{"name":'东城区',"value":101},
{"name":'西城区',"value":102},
{"name":'海淀区',"value":103},
{"name":'朝阳区',"value":104}],
[{"name":'河东区',"value":201},
{"name":'河西区',"value":202},
{"name":'南开区',"value":303}],
[{"name":'石家庄市',"value":301},
{"name":'廊坊市',"value":302},
{"name":'保定市',"value":303},
{"name":'唐山市',"value":304},
{"name":'秦皇岛市',"value":304}]
];
var selProvs = document.getElementsByName("provs")[0];
var selCts = document.getElementsByName("cities")[0];
selProvs.onchange =function(){
var i = this.selectedIndex;
if(i == 0){
selCts.className = "hide";
}else{
selCts.innerHTML = "";
var cts = cities[i-1];
var frag = document.createDocumentFragment();
frag.appendChild(new Option("-请选择-")); //新方法创建option
for(var city of cts){
frag.appendChild(new Option(city.name)); //新方法创建option
}
selCts.appendChild(frag);
selCts.className = "";
}
}
//使用的优化方式:当子元素拥有同一个相同的父元素时,可以先将子元素加入虚拟父元素frag中,再
//将frag添加到真正父元素下,即能把所有子元素一次性添加到真正父元素中,减少layout次数,frag使
//用完成后自动释放
</script> 要点:
1、在select中定义事件需要使用onchange事件,因为会根据option的改变更触发
2、selectedIndex意为获取当前选择option的位置
3、使用hide样式控制隐藏
4、这里的cites[i-1]是因为存在一个option为请选择,如果不用i-1就会错位
5、通过innerHTML可以控制select中的option
6、新方法简便创建option:parent.appendChild(new Option(text,value))
7、定义虚拟父对象frag省去很多创建元素,插入元素的麻烦,增加了渲染速度
如何删除子对象:
parent.removeChild(child)
child.parentNode.removeChild(child)
HTML DOM常用对象,简化创建
1、select/option
常用属性:value 当前选中项的valueselectedIndex 当前选中项的下标
options 获得select下所有option的集合
length 相当于.options.length 获得option的个数
清空option:.length = 0
事件:onchange 当前选中项发生改变时
方法:
Option 创建:var opt = new Option(text,value)
属性:text,value,index
2、table
简单的创建方法:代替document.createElementvar thead = .createTHead()
var tbody = .createTBody()
var tfoot = .createTFoot()
删除:.deleteTHead()
.deleteTFoot()
获取:.tHead()
.Bodies[i] 因为一个表格中可能有很多tbody
.tFoot
行分组:
1、创建行 var tr =.insertRow(i)
固定套路:
1、末尾追加一行:insertRow()
2、开头插入一行:insertRow(0)
删除行:
.deleteRow(i)
问题:i无法自动获得
解决:删除tr的时候首选table.deleteRow(tr.rowIndex)rowIndex是记录tr在整个表中的位置
获取:.rows
tr
创建:var td = parent.insertCell(i)固定用法:末尾追加新格 var td = tr.insertCell()
强调:只能创建td,不能创建th,可以通过样式设置
删除:.deleteCell(i)
获取:.cell
删除行
行分组.deleteRow(i) i是相对于当前行分组内的位置table.deleteRow(tr.rowIndex) rowIndex是相对于整个表中的位置
实例:
<style>
table{width:600px; border-collapse:collapse;
text-align:center;
}
td,th{border:1px solid #ccc}
thead > tr >td{font-weight:bold;}
</style>
</head>
<body>
<div id="data"></div>
<script>
var json=[
{"ename":"Tom", "salary":11000, "age":25},
{"ename":"John", "salary":13000, "age":28},
{"ename":"Mary", "salary":12000, "age":25}
];
//创建一个table
var table=document.createElement("table");
//创建thead
//将thead追加到table下
var thead = table.createTHead(); //简写
//创建tr
//将tr追加到thead下
var tr=thead.insertRow();//新的DOM常用对象行分组写法,减少代码量 var tr = 行分组.insertRow()
//遍历json数组中第一个对象的每个key
for(var key in json[0]){
//创建th
//设置th的内容为key
//将th添加到tr下
tr.insertCell().innerHTML = key;//技巧 链式操作tr.insertCell()返回一个td
}
tr.insertCell().innerHTML = "opr";
//创建tbody
//将tbody追加到table
var tbody=table.createTBody();
//遍历json中每个员工
for(var emp of json){
//创建tr
//将tr追加到tbody中
var tr = tbody.insertRow();//新的DOM常用对象行分组写法,减少代码量 var tr = 行分组.insertRow()
//遍历当前员工的每个属性
for(var key in emp){
//创建td
tr.insertCell().innerHTML = emp[key];
/*var td=
document.createElement("td");
//设置td的内容为key对应的属性值
td.innerHTML=json[i][key];
//将td追加到tr中
tr.appendChild(td);*/
}
/*格中放一个按钮,名为删除*/
var btn = document.createElement("button");
btn.textContent = "删除";
btn.onclick = function(){
var tr = this.parentNode.parentNode; /*技巧:影响数据的操作需要确认*/
//写确认
/*var ename = this.parentNode.previousSibling.previousSibling.previousSibling.textContent;*/
var ename = tr.cells[0].innerHTML;
console.log(ename);
if(confirm(`是否继续删除${ename}?`) == true){
table.deleteRow(tr.rowIndex);}
else{
alert("删除失败");
}
}
tr.insertCell().appendChild(btn);
}
//将table追加到id为data的div下 DOM优化的一种方式,将所有的需要添加到父元素的子元素修改完成后统一添加到父元素中,减少layout
var div=
document.getElementById("data");
div.appendChild(table);
</script>
</body>要点:
1、链式操作,减少代码量
2、简化创建插入操作 var thead = table.createTHead(); var tr = thead.insertRow()等
3、技巧之一:影响数据方面的操作需要确认
4、使用confirm弹出确认取消框来判断是否继续删除
5、通过tr.cell[0].innerHTML获得名字
6、运用deleteRow(tr.rowIndex)删除
7、最后一句将table追加到id为data的div下 运用DOM优化方式-将修改好的子元素统一放入父对象中
Form
获取表单元素的方法:
var form = document.forms[i/id]
属性:
.elements:获得所有表单元素的集合
.length:获得所有表单元素的个数
方法:
form.submit() 代替submit按钮,在程序中手动提交表单
常用来与普通button按钮配合一起实现验证提交
form.reset() 重置表单
Element:
获得任意表单的元素:form.elements[i/id/name]
如果表单元素有name属性:form.name
如果元素没有name而且离结尾很近,就用length去减
方法:
.focus() 获取焦点,一般常在验证出错时强制修改使用
实例:
HTML:<html>
<head>
<meta charset="UTF-8">
<title>实现带样式的表单验证</title>
<link rel="Stylesheet" href="css/3.css" />
</head>
<body>
<form id="form1">
<h2>增加管理员</h2>
<table>
<tr>
<td>姓名:</td>
<td>
<input name="username"/>
<span>*</span>
</td>
<td>
<div class="vali_info">
10个字符以内的字母、数字或下划线的组合
</div>
</td>
</tr>
<tr>
<td>密码:</td>
<td>
<input type="password" name="pwd"/>
<span>*</span>
</td>
<td>
<div class="vali_info">6位数字</div>
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
<input type="button" value="保存"/>
<input type="reset" value="重填"/>
</td>
</tr>
</table>
</form>
<script src="js/3.js"></script>
</body>CSS:
table{width:700px} /*父元素下的第1个,第n个,最后一个td子元素*/ td:first-child{width:60px} /*IE不支持nth-child*/ td:nth-child(2){width:200px} /*IE*/ td:first-child+td{width:200px} /*IE不支持--可以靠总宽度来调节 td:last-child{width:340px}*/ td span{color:red} .vali_info{/* 页面初始,验证消息不显示 */ display:none; } .txt_focus{/*当文本框获得焦点时穿上*/ border-top:2px solid black; border-left:2px solid black; }/*当文本框失去焦点时脱下*/ .vali_success,.vali_fail{ background-repeat:no-repeat; background-position:left center; display:block; } /* 验证消息:验证通过时的样式 */ .vali_success{ background-image:url("../images/ok.png"); padding-left:20px; width:0px;height:20px; overflow:hidden; } /* 验证消息:验证失败时的样式 */ .vali_fail{ background-image:url("../images/err.png"); border:1px solid red; background-color:#ddd; color:Red; padding-left:30px; }JS:
//Step1:为name为username和pwd的文本框绑定获得焦点事件 var form = document.forms[0]; var txtName=form.username; console.log(txtName); var txtPwd= form.pwd; console.log(txtPwd); txtName.onfocus=getFocus; txtPwd.onfocus=getFocus; function getFocus(){ //this->当前文本框 //当前文本框边框加粗 this.className="txt_focus"; //清除旁边div的class var div=this.parentNode .nextElementSibling .firstElementChild; div.className=""; } txtName.onblur=function(){ vali(this,/^\w{1,10}$/); } function vali(txt,reg){ //清除当前文本框的class txt.className=""; //获取旁边div var div=txt.parentNode .nextElementSibling .firstElementChild; //用reg测试当前文本框的内容 //如果通过,就修改div的class为vali_success if(reg.test(txt.value)){ div.className="vali_success"; //添加新的返回值 return true;} //否则修改div的class为vali_fail else{ div.className="vali_fail"; //添加新的返回值 return false; } } txtPwd.onblur=function(){ vali(this,/^\d{6}$/); } //查找倒数第二个提交按钮 //为其绑定单击事件 form.elements[form.length-2].onclick = function(){ //验证用户名和密码 /* var rName = vali(txtName,/^\w{1,10}$/); var rAge = vali(txtPwd,/^\d{6}$/);*/ //如果两次验证都为true if( !vali(txtName,/^\w{1,10}$/)) //如果错误强制获取焦点 txtName.focus(); else if(!vali(txtPwd,/^\d{6}$/)) //如果错误强制获得焦点 txtPwd.focus(); else //如果没错 form.submit();//才提交 }
相关文章推荐
- shell 编程高级技巧
- Qt编程技巧 程序中文乱码解决
- Python的网络编程库Gevent的安装及使用技巧
- VB编程的必备技巧
- Java Applet 编程技巧实例专辑
- 编程技巧:如何使用线程
- VC编程技巧一
- 你的编程技巧已经过时了吗?
- 编程技巧15法之一
- 编程技巧:Mixin(行为继承)
- 提高Java编程性能技巧汇总
- C语言高效编程的的四招技巧
- 【C++编程技巧】根据字符串中的指定字符作为分界将字符串拆分
- 51单片机--LED类编程技巧续
- android用户界面编程技巧——背景和图像的开发技巧
- 一个编程中省资源的技巧
- 【编程技巧】Ext.QuickTips.init();
- MFC SDI单文档 状态栏 进度条 启动画面编程技巧 ...
- AJAX编程技巧:在Struts Action中如何向客户端发送xml文件?
- VC编程小技巧之框架窗口及其他