基于JavaScript创建动态Dom


Posted in Javascript onDecember 08, 2015

动态脚本

我们在页面中使用<script>元素就可以向页面中插入javascript代码。有两种方式:一种是通过src属性引用外部的JS文件,一种是用这个元素来包含一段js代码。所谓的动态脚本,就是指这个脚本在页面加载时不存在,在将来的某一个时刻通过修改DOM来动态的添加脚本。与操作html元素一样,创建动态脚本也有两种方式:插入外部文件和直接插入JavaScript代码。

动态加载的外部JavaScript代码可以立刻被执行,例如下面的代码:

var script = document.createElement("script");
script.type = "text/javascript";
script.src = "demo.js";
document.body.appendChild(script);

基于JavaScript创建动态Dom

从上图的结果中可以看到,上面代码在<body>元素中生成了一个<script>节点:

<script type="text/javascript" src="demo.js"></script>

需要注意的是,在执行最后一行代码把<script>添加到页面之前,是不会下载外部脚本文件的。

另一种指定JavaScript代码的方式是行内方式,例如:

var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode("function fn1(){alert('hello wolrd!')} fn1();"));
document.body.appendChild(script);

基于JavaScript创建动态Dom

上面的代码会在<body>元素中插入一段JavaScript代码:

<script type="text/javascript">
function fn1(){alert('hello wolrd!')} fn1();
</script>

执行上面的代码后会弹出提示框,显示“hello world!”文本。

在Firefox、Safari、Chrome和Opera浏览器中,上面操作的DOM代码是可以正常执行的。但是在旧版本的IE浏览器中,这些代码会发生错误。旧版本的IE浏览器将<script>元素看做特殊元素,不允许DOM访问它的子节点。不过,可以使用<script>元素的text属性来指定JavaScript代码,例如:

var script = document.createElement("script");
script.type = "text/javascript";
script.text("function fn1(){alert('hello wolrd!')} fn1();");
document.body.appendChild(script);

像上面这样修改代码之后,在IE、Firefox、Safari3.0、Chrome和Opera浏览器中都可以运行。Safari3.0之前的浏览器虽然不能正确的执行text属性,但是可以使用文本节点来指定代码。所以如果需要支持旧版本的浏览器,可以像下面这样书写代码:

var script = document.createElement("script");
script.type = "text/javascript";
var code = "function fn1(){alert('hello wolrd!')} fn1();";
try{
script.appendChild(document.createTextNode(code));
}catch(e){
script.text = code;
}

上面的代码首先尝试标准的DOM文本节点方法,因为除了旧版本的IE浏览器之外,其它浏览器都支持这种方式。如果这行代码抛出异常,那么说明是旧版本的IE浏览器,那就必须使用text属性。

我们可以将动态添加脚本的代码封装到一个函数中,通过不同的参数来动态加载不同的脚本。

function loadScript(code){
var script = document.createElement("script");
script.type = "text/javascript";
try{
script.appendChild(document.createTextNode(code));
}catch(e){
script.text = code;
}
document.body.appendChild(script);
}

要调用这个函数,可以像下面的样子:

loadScript("function fn1(){alert('hello wolrd!')}");

这种方式加载的代码会在全局作用域中执行,而且当脚本执行后立刻可用。实际上,这样执行代码与在全局作用域中把相同的字符串传递给eval()函数是一样的。

动态样式

通常可以将CSS样式包含到HTML页面中的元素有两个:一个是<link>元素,用于包含来自外部的文件;另一个是<style>元素,用于指定嵌入样式。与动态脚本类似,动态样式是指在页面加载时并不存在的样式。动态样式是在页面加载完成后动态添加到页面中的脚本。例如下面的例子:

var link = document.createElement("link");
link.rel = "stylesheet"
link.type = "text/css";
link.href = "styles.css";
var head = document.getElementsByTagName("head")[0];

基于JavaScript创建动态Dom

以上的代码在所有主流的浏览器中都可以正常运行。需要注意的是<link>元素要添加到<head>元素中,而不是<body>元素中,才能保证在所有浏览器中的行为一致。

另外要注意的是,加载外部样式文件的过程是异步的,也就是说加载样式和执行JavaScript代码的过程没有固定的次序。

另外一种定义样式的方式是使用<style>元素来包含嵌入式的CSS样式。例如下面的代码:

var style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode("body{background:#f00;}"));
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);

上面的代码执行后可以在<head>元素中动态添加下面的节点:

<style type="text/css">
background:#f00;
</style>

以上的代码可以在Firefox、Safari、Chrome和Opera浏览器中正常运行,在旧版本的IE浏览器中会报错。旧版本的IE浏览器会将<style>元素看做一个特殊的节点,不允许访问它的子节点。要解决旧版本IE的问题,就是访问元素的styleSheet属性,该属性又有一个cssText属性,可以接受CSS代码。例如下面的代码:

var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createTextNode("body{background:#f00;}"));
}catch(e){
style.styleSheet.cssText = "body{background:#f00;}";
}

同样,我们也可以将动态添加样式的代码封装到一个函数中,通过不同的参数来动态加载不同的样式。

function loadStyle(code){
var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createTextNode(code));
}catch(e){
style.styleSheet.cssText = code;
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(style); 
}

JavaScript对表格的操作

在JavaScript中,为了使我们能够方便的构建表格,HTML DOM为表格的<table>、<tbody>和<tr>提供了一些属性和方法。

表格的<table>元素的属性和方法有:

caption:保存<caption>元素的引用的指针。
tBodies:是一个<tbody>元素的HTMLCollection。
tFoot:保存<tfoot>元素的引用的指针。
tHead:保存<thead>元素的引用的指针。
rows:是表格中所有行的HTMLCollection。
createTHead():创建<thead>元素,将它放入表格中,并返回其引用。
createTFoot():创建<tfoot>元素,将它放入表格中,并返回其引用。
createCaption():创建<caption>元素,将它放入表格中,并返回其引用。
deleteTHead():删除<thead>元素。
deleteTFoot():删除<tfoot>元素
deleteCaption():删除<caption>元素
deleteRow(pos):删除指定位置的表格行。
insertRow(pos):向rows集合中指定位置插入一行。

表格的<tbody>元素的属性和方法有:

rows:保存着<tbody>元素中行的HTMLCollection。
deleteRow(pos):删除指定位置的表格行。
insertRow(pos):向rows集合中指定位置插入一行。

表格的<tr>元素的属性和方法有:

cells:保存着<tr>元素中单元格的HTMLCollection。
deleteCell(pos):删除指定位置的单元格。
insertCell(pos):向cells集合中指定位置插入一个单元格,并返回新插入单元格的引用。

使用上面的这些属性和方法,可以使我们轻松的使用JavaScript来创建表格,例如下面的代码:

//创建表格
vatabldocument.createElement("table");
table.borde1;
table.widt"100%";
//创建tbody
vatboddocument.createElement("tbody");
table.appendChild(tbody);
//创建第一个表格行
tbody.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("单元1-1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("单元2-1"));
//创建第二个表格行
tbody.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("单元1-2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("单元2-2"));
//将表格添加到文档中
document.body.appendChild(table)

使用上面的代码可以动态的在页面中创建一个表格。其中在创建表格行的时候,通过<tbody>元素调用了insertCell()方法,并传入参数0(表示将插入的行放在什么位置上)。执行了这一行代码后,会自动创建一个表格行,并将它插入到<tbody>元素的0位置上,此时就可以通过tbody.rows[0]来引用新插入的行。

创建单元格的方式也与创建表格行的方式相同。通过<tr>元素来调用insertCell()方法,并传入要放置单元格的位置。然后就可以通过tbody.rows[0].cells[0]来引用新插入的单元格。

关于NodeList

理解NodeList和NamedNodeMap、HTMLCollection是从整体上理解DOM的关键所在。这3个集合都是动态的,也就是说,每当文档结构发生了变化,它们始终都会保存最新的信息。从本质上来说,所有的NodeList对象都是在访问DOM文档时实时运行的查询。例如下面的代码会导致死循环的出现:

var divs = document.getElementsByTagName("div");
for(var i = 0; i < divs.length; i++){
var div = document.createElement("div");
document.body.appendChild(div);
}

上面的代码首先获取了所有<div>元素的HTMLCollection,保存在一个变量中。由于这个集合是动态的,所以只要有新的<div>被添加到页面中,新的<div>元素就会被添加到这个集合中。这样导致的后果是div.length值是不断变化的,每次循环会在页面中添加一个<div>元素,length的值也会递增。这样i < divs.length条件就永远不会成立,导致死循环的发生。

如果我们要迭代一个NodeList,最好将length属性初始化为第二个变量,然后将迭代器和这个变量做比较,例如:

var divs = document.getElementsByTagName("div");
for(var i = 0,len = divs.length; i < len; i++){
var div = document.createElement("div");
document.body.appendChild(div);
}

由于len中保存了divs.length在循环开始时的一个快照,因此会避免死循环情况的发生。

更多示例:

function sAlert(str){
var msgw,msgh,bordercolor;
msgw=400;//提示窗口的宽度
msgh=100;//提示窗口的高度
titleheight=25 //提示窗口标题高度
bordercolor="#c51100";//提示窗口的边框颜色
titlecolor="#c51100";//提示窗口的标题颜色
var sWidth,sHeight;
sWidth=screen.width;
sHeight=screen.height;
var bgObj=document.createElement("div");
bgObj.setAttribute('id','bgDiv');
bgObj.style.position="absolute";
bgObj.style.top="0";
bgObj.style.background="#cccccc";
bgObj.style.filter="progid:DXImageTransform.Microsoft.Alpha(style=3,opacity=25,finishOpacity=75";
bgObj.style.opacity="0.6";
bgObj.style.left="0";
bgObj.style.width=sWidth + "px";
bgObj.style.height=sHeight + "px";
bgObj.style.zIndex = "10000";
document.body.appendChild(bgObj);
var msgObj=document.createElement("div")
msgObj.setAttribute("id","msgDiv");
msgObj.setAttribute("align","center");
msgObj.style.background="white";
msgObj.style.border="1px solid " + bordercolor;
msgObj.style.position = "absolute";
msgObj.style.left = "50%";
msgObj.style.top = "50%";
msgObj.style.font="12px/1.6em Verdana, Geneva, Arial, Helvetica, sans-serif";
msgObj.style.marginLeft = "-225px" ;
msgObj.style.marginTop = -75+document.documentElement.scrollTop+"px";
msgObj.style.width = msgw + "px";
msgObj.style.height =msgh + "px";
msgObj.style.textAlign = "center";
msgObj.style.lineHeight ="25px";
msgObj.style.zIndex = "10001";
msgObj.style.position = "absolute";
var box=document.getElementById(str);
var title=document.createElement("h4");
title.setAttribute("id","msgTitle");
title.setAttribute("align","right");
title.style.margin="0";
title.style.padding="3px";
title.style.background=bordercolor;
title.style.filter="progid:DXImageTransform.Microsoft.Alpha(startX=20, startY=20, finishX=100, finishY=100,style=1,opacity=75,finishOpacity=100);";
title.style.opacity="0.75";
title.style.border="1px solid " + bordercolor;
title.style.height="18px";
title.style.font="12px Verdana, Geneva, Arial, Helvetica, sans-serif";
title.style.color="white";
title.style.cursor="pointer";
title.onmousedown=function(){startDrag(this,'msgDiv')};
title.onmouseup=function(){stopDrag(this,'msgDiv')};
title.onmousemove=function(){drag('msgDiv')};
var closer=document.createElement("div");
closer.onclick=function(){
CloseReturn();
document.body.appendChild(box);
box.style.display = "none";
document.body.removeChild(bgObj);
document.getElementById("msgDiv").removeChild(title);
document.body.removeChild(msgObj);
};
closer.innerHTML="确定";
document.body.appendChild(msgObj);
document.getElementById("msgDiv").appendChild(title);
document.getElementById("msgTitle").appendChild(closer);
box.style.display="inline";
document.getElementById("msgDiv").appendChild(box);
ShowReturn();
}

html dom树:

基于JavaScript创建动态Dom

Javascript 相关文章推荐
用js实现控制内容的向上向下滚动效果
Jun 26 Javascript
jQuery+AJAX实现无刷新下拉加载更多
Jul 03 Javascript
利用jQuery实现WordPress中@的ID悬浮显示评论内容
Dec 11 Javascript
Vue数据驱动模拟实现5
Jan 13 Javascript
vue脚手架vue-cli的学习使用教程
Jun 06 Javascript
浅谈node中的exports与module.exports的关系
Aug 01 Javascript
Angular2.0实现modal对话框的方法示例
Feb 18 Javascript
浅谈Angularjs中不同类型的双向数据绑定
Jul 16 Javascript
webpack4.0+vue2.0利用批处理生成前端单页或多页应用的方法
Jun 28 Javascript
基于mpvue的简单弹窗组件mptoast使用详解
Aug 02 Javascript
浅析微信小程序modal弹窗关闭默认会执行cancel问题
Oct 14 Javascript
jquery实现加载更多&quot;转圈圈&quot;效果(示例代码)
Nov 09 jQuery
jQuery实现form表单基于ajax无刷新提交方法详解
Dec 08 #Javascript
JS判断当前页面是否在微信浏览器打开的方法
Dec 08 #Javascript
js实现兼容IE、Firefox的图片缩放代码
Dec 08 #Javascript
JS实现按比例缩放图片的方法(附C#版代码)
Dec 08 #Javascript
JS获取文件大小方法小结
Dec 08 #Javascript
js+ajax实现获取文件大小的方法
Dec 08 #Javascript
JS表格组件神器bootstrap table详解(基础版)
Dec 08 #Javascript
You might like
重置版游戏视频
2020/04/09 魔兽争霸
php 基础函数
2017/02/10 PHP
ThinkPHP3.2.3框架邮件发送功能图文实例详解
2019/04/23 PHP
Open and Print a Word Document
2007/06/15 Javascript
extjs grid取到数据而不显示的解决
2008/12/29 Javascript
JavaScript中的style.cssText使用教程
2014/11/06 Javascript
JavaScript获取页面中表单(form)数量的方法
2015/04/03 Javascript
简介JavaScript中的setTime()方法的使用
2015/06/11 Javascript
原生js实现ajax方法(超简单)
2016/09/20 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
2017/09/20 jQuery
vue2.0 computed 计算list循环后累加值的实例
2018/03/07 Javascript
微信小程序防止多次点击跳转(函数节流)
2019/09/19 Javascript
微信小程序如何实现radio单选框单击打勾和取消
2020/01/21 Javascript
javascript实现滚动条效果
2020/03/24 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
vue实现简单全选和反选功能
2020/09/15 Javascript
[15:07]lgd_OG_m2_BP
2019/09/10 DOTA
Python入门篇之数字
2014/10/20 Python
python开发中module模块用法实例分析
2015/11/12 Python
Python如何快速上手? 快速掌握一门新语言的方法
2017/11/14 Python
python 获取list特定元素下标的实例讲解
2018/04/09 Python
python skimage 连通性区域检测方法
2018/06/21 Python
朴素贝叶斯分类算法原理与Python实现与使用方法案例
2018/06/26 Python
Python3网络爬虫开发实战之极验滑动验证码的识别
2019/08/02 Python
浅谈anaconda python 版本对应关系
2020/10/07 Python
CSS3实现歌词进度文字颜色填充变化动态效果的思路详解
2020/06/02 HTML / CSS
基于第一个PhoneGap(cordova)的应用详解
2013/05/03 HTML / CSS
为中国消费者甄选天下优品:网易严选
2016/08/11 全球购物
控制工程专业个人求职信
2013/09/25 职场文书
职高毕业生自我鉴定
2013/10/21 职场文书
医科大学生毕业的自我评价分享
2013/11/12 职场文书
降消项目实施方案
2014/03/30 职场文书
《认识钟表》教学反思
2016/02/16 职场文书
《倍数和因数》教学反思
2016/02/23 职场文书
《狼王梦》读后感:可怜天下父母心
2019/11/01 职场文书
Mysql binlog日志文件过大的解决
2021/10/05 MySQL