案例

案例 – JS实现留言(DOM练习)

1
2
3
4
5
6
7
DOM 是 Document Object Model(文档对象模型)的缩写。
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
1)整个文档是一个文档节点
2)每个 HTML 元素是元素节点
3)HTML 元素内的文本是文本节点
4)每个 HTML 属性是属性节点
5)注释是注释节点

js实现留言板

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="wrap">
<p>姓名:<input type="text" id="username" value=""/></p>
<p>内容:<textarea rows="10" cols="35" id="message"></textarea></p>
<p class="p"><input type="button" id="btn" value="提交" /></p>
<div class="d">
<h2>显示留言</h2>
</div>
<ul>
<!--<li>
<div>1</div><div><span>1</span><a href="###">删除</a></div>
</li>-->

</ul>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
html,body{
margin: 0;
padding: 0;
}
.wrap{
width: 500px;
min-height: 500px;
margin: auto;
background-color: #ddd;
padding-top: 10px;
}
#username{
width: 410px;
height: 30px;
font-size: 20px;
border: 1px solid #bbb;
vertical-align: middle;
}
p{
width: 500px;
line-height: 16px;
text-align: center;
font-weight: bolder;
}
textarea{
vertical-align: text-top;
font-size: 20px;
border: 1px solid #bbb;
}
.p{
width: 220px;
}
#btn{
width: 90px;
height: 30px;
border: 1px solid #bbb;
background: white;
}
.d{
width: 450px;
margin: auto;
}
ul{
list-style: none;
margin: 0;
padding: 0;
}
li{
border-bottom: 1px solid #999999;
height: 80px;
overflow: hidden;
/*margin-bottom: 10px;*/
}
li div{
width: 450px;
margin: auto;
}
li div:nth-child(1){
width: 435px;
background: #999;
line-height: 30px;
padding-left: 1em;
}
li div:nth-child(2){
background: white;
min-height: 40px;
overflow: hidden;
}
ul li span{
text-indent: 3em;
float: left;
}
ul li a{
float: right;
margin-right: 1em;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* 知识点
* Selector参照jQuery的元素获取,通过css选择器获取元素
*querySelector获取一个元素,如果有多个同名的只选择第一个
*querySelectorAll获取一组元素,结果得到一个数组,使用方法与数组一样
*/

//获取姓名文本框
var username = document.querySelector('#username');
//获取内容文本框
var message = document.querySelector('#message');
//获取按钮
var btn = document.querySelector('#btn');
//获取留言区ul
var ul = document.querySelector('ul');

//按钮点击事件
btn.onclick = function (){
//判断文本框是否为空,一个为空都要执行if里的代码块
if (username.value == '' || message.value == '') {
alert('请输入完整信息!');
return;
}
/*
* 知识点
* 在document(文档)中创建一个标签节点 document.createElement(obj)
* 在元素里的后面添加 obj.appendChild(newNode)
* 在元素里某个节点前面添加 obj.insertBefore(newNode, node)
* 在元素里替换某个节点 obj.replaceChild(newNode, oldNode)
* 在元素里移除某个节点 obj.removeChild(node)
* 在元素里添加文本/HTML代码 obj.innerHTML = 文本/HTML代码
* 获取文本框的光标 input.focus()
*/

var li = document.createElement('li');//创建一个li节点
//给li添加内容
li.innerHTML = '<div>'+username.value+'</div><div><span>'+message.value+'</span><a href="###">删除</a></div>';
li.style.height = '0px';//高度设为0
ul.appendChild(li);//在ul里面的最后面添加li
myFn(li,80);//启动动画函数
message.value = '';//清空内容
message.focus();//让内容文本框获取光标
//获取当前li里的删除标签
var a = li.querySelector('a');
//设置当前li里的删除标签的点击事件
a.onclick = function(){
//启动动画函数
myFn(li,0,function(obj){
//在动画末端添加函数执行另外操作
ul.removeChild(obj);//移除当前a的爷爷li
//退出函数
return;
});
}
}
/*
* 函数注释
* 改变元素高度动画函数
* obj参数是你的元素,不可为空
* end参数是最终高度,不可为空
* fn参数是计时器结束后执行的回调函数,可为空
*/

function myFn(obj,end,fn){
var start = parseInt(getStyle(obj,'height')) ;
//初始高度
var change = end - start;
//改变的高度值
var t = 0;
//第几步开始
var endT = 30;
//执行步数
var timer = setInterval(function(){
//设置计时器
t++;
//每30毫秒加一步
if(t >= endT){
//当到达第30步时执行if里的代码块
clearInterval(timer);
//endT步后清除计时器
//如果fn是一个函数则执行fn(),否则不执行
fn && fn(obj);
}
var h = Tween.Bounce.easeOut(t, start, change, endT);//计算每30毫秒移动的距离
obj.style.height = h+'px';
},30);
}
/*
* 函数注释
* 获取元素非行内样式函数
* obj参数是你的元素,不可为空
* attr参数是样式属性,不可为空
* 返回的是属性值
*/

function getStyle(obj,attr){
/*
* 知识点
* currentStyle IE下有,非IE下没有
* getComputedStyle 非IE下有,IE下没有
*/

//判断是否有obj.currentStyle,有就返回obj.currentStyle[attr],没有返回getComputedStyle(obj,null)[attr]
return obj.currentStyle?obj.currentStyle[attr]:getComputedStyle(obj,null)[attr];
}

补充知识点

复制节点

1
2
3
4
<div style="background: bisque;">
I'm Div
<span>I'm Span</span>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
var div =document.querySelector('div');
/*
* cloneNode:复制节点 参数为布尔值
* 参数为false:浅复制,只复制标签
* 参数为true: 深复制,复制标签所有内容
*/

var clone_div = div.cloneNode(false);
clone_div.innerHTML += "浅复制";
var clone_div1 = div.cloneNode(true);
clone_div1.innerHTML += "深复制";
document.body.appendChild(clone_div);
document.body.appendChild(clone_div1);

标签属性操作

1
2
3
<div id="d1" class="d1" abc="a" index="0">
I'm Div
</div>
1
2
3
4
5
6
7
8
9
10
11
var div = document.getElementById('d1');
//alert(div.index);//undefined
//获取标签里的属性
alert(div.getAttribute("index"));//0
//修改标签里的属性
div.setAttribute('index', '5');
alert(div.getAttribute("index"));//5
//删除标签里的属性
alert(div.getAttribute("abc"));//a
div.removeAttribute('abc');
alert(div.getAttribute("abc"));//null

children

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
var ul = document.querySelector('ul');
//children获取所有是标签类型的子节点
var li = ul.children;
//获取ul里所有标签子节点
for (var i = 0; i<li.length;i++) {
if(i%2 == 0){
li[i].style.background = 'lavender'
}else{
li[i].style.background = 'blanchedalmond'
}
}
var l11 = li[9].children[0].children[1];
l11.style.background = 'forestgreen';

查找节点

1
2
3
4
5
6
7
8
9
10
11
12
ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
var ul = document.querySelector('ul');
var li = ul.children;
/*
* nextSibling
* 在IE下nextSibling查找的下一个节点只有节点类型为标签的节点,非IE下查找下一个节点为节点类型所有类型节点
*/

//alert(li[0].nextSibling.nodeName);//#text
//解决方法
//if(li[0].nextElementSibling){
//li[0].nextElementSibling.style.background = 'forestgreen';//非IE的方法(IE下没有这一方法)
//}else{
//li[0].nextSibling.style.background = 'forestgreen';
//IE的方法
//}
//***************************************************************************

//查找下一个节点函数
/*
* obj参数为当前标签元素
*/

function nextFn (obj) {
return obj.nextElementSibling?obj.nextElementSibling:obj.nextSibling;
}
//调用
nextFn(li[1]).style.background = 'burlywood';

//****************************************************************************

//查找上一个节点函数
/*
* obj参数为当前标签元素
*/

function previousFn(obj){
return obj.previousElementSibling?obj.previousElementSibling:obj.previousSibling;
}
//调用
previousFn(li[4]).style.background = 'skyblue';

//***************************************************************************

//查找第一个子节点函数
/*
* obj参数为第一个子节点的父级标签元素
*/

function firstFn(obj){
return obj.firstElementChild?obj.firstElementChild:obj.firstChild;
}
//调用
firstFn(ul).style.background = 'palegreen';

//*****************************************************************************

//查找最后一个子节点函数
/*
* obj参数为最后一个子节点的父级标签元素
*/

function lastFn(obj){
return obj.lastElementChild?obj.lastElementChild:obj.lastChild;
}
//调用
lastFn(ul).style.background = 'coral';

//******************************************************************************

查找元素在文档的top和left

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
*offsetFn 查找元素在文档的top和left
*obj 目标元素 不可为空
*逐级询问父子的top和left 并返回json
*/

function offsetFn(obj) {
var t = 0;
var l = 0;
while(obj){
var bT = parseInt(getStyle(obj,"borderTopWidth"));
var bL = parseInt(getStyle(obj,"borderLeftWidth"));
t += obj.offsetTop + bT ;
l += obj.offsetLeft + bL;
obj = obj.offsetParent;
}
return {"top":t,"left":l};
}
/*
* 函数注释
* 获取元素非行内样式函数
* obj参数是你的元素,不可为空
* attr参数是样式属性,不可为空
* 返回的是属性值
*/

function getStyle(obj,attr) {
if (obj.currentStyle) {
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,null)[attr];
}
}
//调用
var Dtop = offsetFn(div).top;
var Dleft = offsetFn(div).left;