DOM是一套编程接口,让js能操作html和xml。
1. DOM选择器
1.1 document.getElementById()
- 其中元素id在ie8以下的浏览器不区分大小写
- 该方法定义在 Document.prototype上,即Element节点上不能使用
1.2 getElementsByTagName()
- 该方法定义在 Document.prototype 和 Element.prototype上, 最常用的一个方法
<div>
<span>sun</span>
</div>
<span></span>
<script>
var div = document.getElementsByTagName('div')[0];
var span = div.getElementsByTagName('span')[0];
</script>
1.3 getElementsByName()
- 其中只有部分标签的name可生效,例如 表单,表单元素, img, iframe...
- 方法定义在 HTMLDocument.prototype上
1.4 getElementsByClassName()
- 类名,其中ie8和ie8以下的ie版本中没有
- 该方法定义在 Document.prototype 和 Element.prototype上
1.5 querySelector()
和 querySelectorAll()
- css选择器,在ie7和ie7以下的版本中没有
- querySelector 选出来的是一个, querySelectorAll 选出来是一组。
- 这俩方法选出来的不是实时的。
- 这俩方法定义在 Document.prototype 和 Element.prototype上
<div>
<span>
<strong class="demo"><strong>
</span>
</div>
<script>
var strong = document.querySelector('div > span strong.demo')
</script>
2. 遍历节点树
-
parentNode
父节点(最顶端的parentNode为 #document)
<div>
<strong></strong>
<span></span>
<em></em>
</div>
<script>
var strong = document.getElementsByTagName('strong')[0];
</script>
-
childNodes
选出子节点们
<div>
<strong>
<span></span>
</strong>
<span></span>
<em></em>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
需要注意的是,这个东西选出来的子节点们,是会把所有类型的子节点都选出来。什么 文本节点,注释节点,元素节点... ...(节点的类型在后文会有写)
-
firstChild
第一个子节点 -
lastChild
最后一个子节点, 即能选择元素中的最后一个节点。 -
nextSibling
&previousSibling
后/ 前一个兄弟节点
<div>
<strong>
<span></span>
</strong>
<span></span>
<em></em>
</div>
<script>
var strong = document.getElementsByTagName('strong')[0];
</script>
strong
的下一个兄弟节点是文本节点,再下一个兄弟节点是 span
... ...
3. 基于元素节点树的遍历
下面这些方法遍历时,是基于真正的元素节点;即文本节点,注释节点等等都不会识别了。
注意: 下面的 ie不兼容 指的是 ie9 和 ie9 以下的。
-
parentElement
返回当前元素的 父元素的节点(ie不兼容)
<div>
sun
<!-- 嘤嘤嘤 -->
<strong></strong>
<span></span>
</div>
<script>
var strong = document.getElementsByTagName('strong')[0];
</script>
需要明白的是,document
自成一个节点,不是元素节点。也就是 parentElement
和 上面那个parentNode
出来结果不一样的地方。
-
children
只返回当前元素的元素子节点们
<div>
<!-- 嘤嘤嘤 -->
<strong></strong>
<span></span>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
-
node.childElementCount === node.children.length
当前元素节点的子元素节点个数 (ie不兼容) -
firstElementChild
&lastElementChild
返回的是第一个/ 最后一个元素子节点 (ie不兼容)
<div>
<strong></strong>
<span></span>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
-
nextElementSibling
/previousElementSibling
返回后一个/ 前一个兄弟元素节点
3.1 节点的四个属性
-
nodeName
元素的标签名,返回一个字符串;只读。
<div>
sun
<!--嘤嘤嘤-->
<strong></strong>
<span></span>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
nodeValue
只有 Text (文本)节点 和 Comment (注释)节点有这个属性;可读写;-
nodeType
(重点)
该节点的类型;只读。
获取节点类型:
attributes
元素的Element 节点的属性集合
3.2 节点的类型
- 1 --- 元素节点
- 2 --- 属性节点
- 3 --- 文本节点
- 8 --- 注释节点
- 9 --- 文档节点 (document)
3.4 节点的一个方法:Node.hasChildNodes()
返回值: true / false
<div>
<strong></strong>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
注意: 是找有没有节点,不是有没有元素节点,所以下列两种情况皆返回
true
:
<!--这坨div中含有注释节点-->
<div>
<!--嘤嘤嘤-->
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
<!--这坨div中含有文本节点-->
<div>
</div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
下面这种情况返回 false
:
<div></div>
<script>
var div= document.getElementsByTagName('div')[0];
</script>
4. DOM结构树 (表示一种继承关系)
- 继承关系:
document
---->HTMLDocument.prototype
---->Document.prototype
即: HTMLDocument.prototype = { __proto__: Document.prototype}
- HTMLDocument.prototype 定义了一些常用的属性, body, head 分别指代 HTML 文档中的
<body>
和<head>
标签; 用法:document.body
,document.head
- Document.prototype 上定义了
documentElement
属性,指代文档的根元素,在HTML文档中,他总是指代<html>
元素;用法:document.documentElement
5. DOM 基本操作
5.1 增
- document.createElement();
创建元素节点:document.createElement('div');
- document.createTextNode();
创建文本节点:document.createTextNode('啦啦啦,德玛西亚');
- document.createComment();
创建注释节点:document.createComment('这是注释嗷');
- document.createDocumentFragment();
创建文档碎片节点
5.2 插
- PARENTNODE.appendChild();
任何一个元素节点都有这个方法。
<body>
<script>
var div = document.createElement('div');
document.body.appendChild(div);
</script>
</body>
如果把页面中已经存在的一个部分,appendChild去另一个部分,做的是 剪切 操作。
<body>
<div></div>
<span></span>
<script>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
div.appendChild(span);
</script>
</body>
- ParentNode.insertBefore(a, b);
必须父级去调用,然后往父级里面放东西。(把 a 放到 b 前面)
<body>
<div>
<span></span>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var strong = document.createElement('strong');
div.insertBefore(strong, span);
</script>
</body>
5.3 删
- parent.removeChild();
父节点删除子节点, 该方法返回被删除的子节点
<body>
<div>
<span></span>
<i></i>
<strong></strong>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var i = document.getElementsByTagName('i')[0];
div.removeChild(i);
</script>
</body>
- child.remove();
自己销毁自己,返回 undefined
<body>
<div>
<span></span>
<i></i>
<strong></strong>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
span.remove();
</script>
</body>
5.4 替换
- parent.replaceChild(new, origin);
拿新的元素(new)去替换旧的元素(origin)
<body>
<div>
<span></span>
<i></i>
<strong></strong>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
</script>
</body>
5.4 Element 节点的一些属性
- innerHTML
改变一个元素里面的html内容
<body>
<div>
<span>sun</span>
<p>sweet</p>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
</script>
</body>
-
innerText
取一个元素中的文本内容。
5.5 Element 节点的一些方法
- ele.setAttribute();
<body>
<div></div>
<script>
var div = document.getElementsByTagName('div')[0];
div.setAttribute('class', 'test');
</script>
</body>
-
ele.getAttribute();
6. date对象
日期对象 Date()
。打印当前是何年何月何日何时,几分几秒。
var date = new Date();
-
getDate()
这个方法会返回今天是这个月中的第几天 (今天是5月1)
-
getDay()
注意: 周天是第一天
这个方法会返回今天是一周中的第几天(0~6)
-
getMonth()
注意: 从0开始计算,1月为0
这个方法会返回当前是几月(0 ~11)
-
getFullYear()
这个方法会返回当前是几几年
-
getHours()/ getMinutes()/ getSeconds()
注意:这个返回的是创建时候那个时刻的时分秒 (我电脑的时间是 14:01)
返回Date对象的小时/分钟/秒数
getTime() 重点嗷~~~
- 这个方法返回1970年1月1日至今的毫秒数;
- 这个方法可以求时间戳
下面这段代码可以求证1000000次循环用了多少时间。结果显示为 4毫秒。
<script>
var firstTime = new Date().getTime();
for(var i=0; i<1000000; i++) {}
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
</script>
-
setDate()
这个方法可以设置Date对象中 月的某一天(1~31)
-
toString()
把 Date对象转换为字符串
7. js定时器
注意:都是全局对象 window 上的方法,内部函数 this 指向 window。
- setInterval()
- 每隔1000毫秒就执行一次函数
- 它会返回一个数字作为它的唯一表示 (表示这是第几个定时器)
var timer = setInterval(function() {
console.log('sun');
}, 1000) ;
- setTimeout()
- 推时作用, 推迟多少时间之后才执行某个操作, 并且只执行一次。
var timer = setTimeout(function () {
console.log('sun');
}, 1000);
- clearInterval()
清除定时器
var i = 0;
var timer = setInterval(function() {
console.log(i ++);
if (i > 10) {
clearInterval(timer);
}
}, 10) ;
- clearTimeout()
var timer = setTimeout(function() {
console.log('a');
}, 1000);
clearTimeout(timer);
8. 用dom获取界面尺寸
1. 查看滚动条的滚动距离
语法: window.pageXOffset/ pageYOffset
(IE及IE8以下不兼容)
语法: document.body/documentElement.scrollLeft/ scrollTop
(IE8及IE8以下用这个方法去求滚动条的滚动距离)
注意: IE8和IE8以下以下的浏览器, document.body.scrollLeft/Top
和 document.documentElement.scrollLeft/Top
这两个由于兼容性问题,只有一个会生效。所以说以后用的话直接把两个加一加。
document.body.scrollLeft + document.documentElement.scrollLeft
封装一个方法,使滚动条的滚动距离能兼容所有浏览器
function getScrollOffset() {
if(window.pageXOffset) {
return {
x: window.pageXOffset,
y: window.pageYOffset
}
} else {
return {
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
2. 查看可视区窗口的尺寸
可视区窗口其实就是 html 文档的部分。
语法:window.innerWidth/innerHeight
(IE8及IE8以下不兼容)
语法:document.documentElement.clientWidth/clientHeight
(标准模式下,任意浏览器都兼容; IE8及IE8以下是可以兼容的)
语法: document.body.clientWidth/clientHeight
(怪异/ 混杂模式模式下; IE8及IE8以下是可以兼容的)
科普:混杂模式启用方法
<!DOCTYPE html>
这句话删了就启用了混杂模式了。写了这句话就是标准模式。
封装一个方法,获取可视区窗口的尺寸,兼容所有浏览器
function getViewportOffset() {
if(window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else {
if (document.compatMode === "BackCompat") {
return {
w: document.body.clientWidth,
h: document.body.clientHeight
}
} else {
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
}
}
}
}
3. 查看元素的几何尺寸
该方法兼容性很好。 任何一个dom元素都有这个方法。
语法: domEle.getBoundingClientRect()
该方法返回一个对象。需要注意的是,这个返回的结果并不是实时的。(讲道理,这个方法没什么用,稍微看一看。)
<body>
<div style="width: 50px; height: 50px; background-color: pink;
position: absolute; left: 100px; top: 100px;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
</script>
</body>
4. 查看元素尺寸
语法: dom.offsetWidth
, dom.offsetHeight
5. 查看元素的位置
语法:dom.offsetLeft
, dom.offsetTop
注意:这个方法会忽略元素自身是否是定位元素,求得值是距离它有定位的父级的坐标。如果对于无定位父级的元素,则返回的值是相对文档的坐标。
语法:dom.offsetParent
该方法能求出相对于最近的有定位的父级,如果没有,就返回body
6. 让滚动条滚动
window上有三个方法:
-
scroll()
/scrollTo()
这俩方法没区别,喜欢用哪个就用哪个吧。滚动到指定的点。
里面可以填俩参数,第一个参数是让x轴滚动的距离,第二个参数是让y轴滚动的距离
<div style="width: 5000px; height: 5000px;
border: 1px solid black"></div>
-
scroll By()
累加滚动距离,用法和上面类似,只不过这个可以累加。
9. 脚本化 CSS
- 读写元素css属性
- dom.style.prop
这个可以读写 行间样式
注意: - 在js访问css属性时,不能访问有
-
的属性,例如background-color
。所以但凡碰到这样的,改成小驼峰式就可以访问了。即backgroundColor
- 碰到关键字的时候,例如
float
,写成cssFloat
- 写入的值必须是字符串格式
<body>
<div style="width: 50px; height: 50px; background-color:pink;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
div.style.backgroundColor = 'red';
div.style.width = '200px';
</script>
</body>
- 查询计算样式
获取的是当前元素所展示出的一切css的显示值
window.getComputedStyle()
-
第一个参数填你要获取的是哪个元素,第二个参数一般情况下填null,这个参数可以获取伪元素的样式表
- 这个方法只读,不能改。
- 该方法返回的值都是绝对值,没有相对单位
- IE8及IE8以下不兼容
所以IE8和IE8以下的浏览器,查询样式使用的方法如下:
window.currentStyle['prop']
- 计算样式只读
- IE独有属性
封装兼容性方法获取css style
function getStyle(elem, prop) {
if(window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
} else {
return elem.currentStyle[prop];
}
}
10. 事件
1. 绑定事件的几种方法
-
ele.onxxx = function (event) {}
兼容性很好,但是一个元素的同一个事件上只能绑定一个处理程序。基本等同于写在html行间上。
程序this指向dom元素本身。
<div></div>
... ...
var div = document.getElementsByTagName('div')[0];
div.onclick = function() {
this.style.backgroundColor = 'green';
}
-
obj.addEventListener(type, fn, false);
IE9以下不兼容,可以为一个事件绑定多个处理程序。
程序this指向dom元素本身。
div.addEventListener('click', function() {
} , false);
-
obj.attachEvent('on' + type, fn)
IE独有,一个事件同样可以绑定多个处理程序。
程序this指向window。
如果想让this指向div,方式如下:
div.attachEvent('onclick', function() {
handle.call(div);
})
function handle() {
this.xxx = xxxxxxxxx;
}
封装兼容性方法 addEvent(elem, type, handle)
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if(elem.attachEvent) {
elem.attachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = handle;
}
}
2. 解除事件处理程序
注意:如果绑定的是匿名函数,则无法解除。
ele.onclick = false/''/null;
var div = document.getElementsByTagName('div')[0];
// 只执行一次事件
div.onclick = function() {
console.log('a');
this.onclick = null;
}
ele.removeEventListener(type, fn, false);
var div = document.getElementsByTagName('div')[0];
function test() {
console.log('sun');
}
div.addEventListener('click', test, false);
div.removeEventListener('click', test, false);
ele.detachEvent('on' + type, fn)
11. 事件处理模型
一个对象的一个事件类型只能遵循一种模型。
如果一个对象的一个事件类型上绑定了两个函数,两个函数分别遵循捕获和冒泡,那么执行顺序为 先捕获后冒泡。
1. 事件冒泡
- 结构上嵌套关系(就是父子关系)的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
- 特殊事件没有冒泡功能:
focus
,blur
,change
,submit
,reset
,select
等
<style>
.wrapper{
width: 300px;
height: 300px;
background-color: red;
}
.content {
width: 200px;
height: 200px;
background-color: green;
}
.box {
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
... ...
<body>
<div class="wrapper">
<div class="content">
<div class="box"></div>
</div>
</div>
<script>
var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var box = document.getElementsByClassName('box')[0];
wrapper.addEventListener('click', function() {
console.log('wrapper');
}, false);
content.addEventListener('click', function() {
console.log('content');
}, false);
box.addEventListener('click', function() {
console.log('box');
}, false);
</script>
</body>
2. 事件捕获
- 与冒泡顺序相反,结构上嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素。(自顶向下)
- 注意:IE没有捕获事件
<style>
.wrapper{
width: 300px;
height: 300px;
background-color: red;
}
.content {
width: 200px;
height: 200px;
background-color: green;
}
.box {
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
... ...
<body>
<div class="wrapper">
<div class="content">
<div class="box"></div>
</div>
</div>
<script>
var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var box = document.getElementsByClassName('box')[0];
wrapper.addEventListener('click', function() {
console.log('wrapper');
}, true);
content.addEventListener('click', function() {
console.log('content');
}, true);
box.addEventListener('click', function() {
console.log('box');
}, true);
</script>
</body>
3. 阻止事件冒泡
-
event.stopPropagation()
, 该方法不支持IE9以下版本。
<style>
.wrapper {
width: 300px;
height: 300px;
background-color: red;
}
</style>
... ...
<body>
<div class="wrapper"></div>
<script>
var div = document.getElementsByTagName('div')[0];
document.onclick = function() {
console.log('点我干啥');
}
div.onclick = function(e) {
e.stopPropagation();
this.style.background = "orange";
}
</script>
</body>
-
event.cancelBubble = true
, 该方法兼容IE。
<body>
<div class="wrapper"></div>
<script>
var div = document.getElementsByTagName('div')[0];
document.onclick = function() {
console.log('点我干啥');
}
div.onclick = function(e) {
e.cancelBubble = true;
this.style.background = "orange";
}
</script>
</body>
- 封装取消冒泡函数
function stopBubble(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
4. 阻止默认事件
默认事件 —— 表单提交, a标签跳转, 右键菜单等。
科普科普,右键出菜单事件 document.oncontextmenu = function() {}
。
-
return false;
,以对象属性的方式注册的事件才生效
document.oncontextmenu = function() {
console.log('a');
return false;
}
-
event.preventDefault();
,该方法IE9以下不支持
document.oncontextmenu = function(e) {
console.log('a');
e.preventDefault();
}
-
event.returnValue = false;
,该方法兼容IE
document.oncontextmenu = function(e) {
console.log('a');
e.returnValue = false;
}
- 封装阻止默认事件函数
// 使用
document.oncontextmenu = function(e) {
console.log('sun');
cancelHandler(e);
};
// 封装的函数
function cancelHandler(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
5. 事件对象
-
event || window.event
兼容IE的写法
<script>
var div = document.getElementsByTagName('div')[0];
div.onclick = function(e) {
var event = e || window.event;
console.log(event);
}
</script>
- 事件源对象:
-
event.target
火狐只有这个 -
event.srcElement
IE只有这个 - chrome 这俩都有
- 封装一个兼容函数,获取事件源对象
<body> <div class="wrapper"> <div class="box"></div> </div> <script> var wrapper = document.getElementsByClassName('wrapper')[0]; var box = document.getElementsByClassName('box')[0]; wrapper.onclick = function(e) { var event = e || window.event; var target = event.target || event.srcElement; console.log(target); } </script> </body>
-
6. 事件委托
- 利用事件冒泡和事件源对象进行处理
- 性能好,不需要循环所有的元素一个个去绑定事件
- 灵活,当有新的子元素时,不需要重新绑定事件
<body>
<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>
<script>
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e) {
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(target.innerText);
}
</script>
</body>
12. 事件分类
1. 鼠标事件
click
,mousedown
,mousemove
,mouseup
,contextmenu
,mouseover
,mouseout
,mouseenter
,mouseleave
用 button 来区分鼠标的按键, 0/1/2
document.onmousedown = function(e) {
console.log(e);
if (e.button == 2) {
console.log('right');
} else if (e.button == 0) {
console.log('left');
}
}
click 事件只能监听左键,只能通过
mousedown
和mouseup
来判断鼠标键。 右键无法触发click事件。解决
mousedown
和click
的冲突
用时间差来进行判断。
var firstTime = 0;
var lastTime = 0;
var key = false;
document.onmousedown = function() {
firstTime = new Date().getTime();
}
document.onmouseup = function() {
lastTime = new Date().getTime();
if (lastTime - firstTime < 300) {
key = true;
}
}
document.onclick = function() {
if (key) {
console.log('click');
key = false;
}
}
2. 键盘事件
keydown
,keyup
,keypress
触发顺序:keydown > keypress > keyupkeydown 和 keypress 的区别
keydown 可以响应任意键盘按键, keypress 只响应字符类键盘按键。
keypress 返回 ASCII 码,可以转换成相应字符。
<script>
document.onkeypress = function (e) {
console.log(String.fromCharCode(e.charCode));
}
</script>
3. 移动端事件
touchstart
touchmove
touchend
4. 事件分类
- 文本类事件
input
,change
,focus
,blur
。
<input type="text">
... ...
// 但凡文本有变化,就会触发input事件
var input = document.getElementsByTagName('input')[0];
input.oninput = function (e) {
console.log(this.value);
}
// 聚焦,改变内容,失去焦点,触发change事件
input.onchange= function (e) {
console.log(this.value);
}
- 窗体操作类 (window上的事件)
scroll
当滚动条一滚动,这个事件就会被触发;
load
这个方法是最慢的,这个页面所有要加载的要初始化的东西全部完成后,这个方法才会触发。
window.onscroll = function () {
console.log(window.pageXOffset + ' ' + window.pageYOffset);
}
window.onload = function () {
// 没事情别用这个瓜皮方法
}
小知识:
浏览器有个时间线:
(html和css是并行解析的)
html在解析的时候会形成一个 domTree;所有的dom解析完毕,不是下载完。
css在解析的时候会形成一个 cssTree;
这俩会形成一个 renderTree;
练习
- 遍历元素节点树 (在原型链上编程)
- 封装函数,返回元素e的第n层祖先元素节点
function retParent(elem, n) {
while(elem && n) {
elem = elem.parentElement;
n--;
}
return elem;
}
- 封装函数,返回元素e的第n个兄弟元素节点,n为正,返回后面的兄弟元素节点,n为负,返回前面的,n为0,返回自己。
- 不考虑兼容性
function retSibling(e, n) {
while(e && n) {
if(n > 0) {
e = e.nextElementSibling;
n--;
} else {
e = e.previousElementSibling;
n++;
}
return e;
}
}
- 考虑兼容性
function retSibling(e, n) {
while(e && n) {
if(n > 0) {
if(e.nextElementSibling) {
e = e.nextElementSibling;
} else {
for(e=e.nextSibling; e && e.nodeType != 1; e = e.nextSibling);
}
n--;
} else {
if(e.previousElementSibling) {
e = e.previousElementSibling;
} else {
for(e = e.previousSibling; e && e.nodeType != 1; e = e.previousSibling);
}
n++;
}
return e;
}
}
- 编辑函数,封装myChildren功能,解决以前部分浏览器的兼容性问题。(找该元素的子元素节点)
Element.prototype.myChildren = function() {
var child = this.childNodes;
var len = child.length;
var arr = [];
for(var i=0; i<len; i++) {
if(child[i].nodeType ==1) {
arr.push(child[i]);
}
}
return arr;
}
- 自己封装hasChildren()方法,不可用children属性。
Element.prototype.myChildren = function() {
var child = this.childNodes;
var len = child.length;
for(var i=0; i<len; i++) {
if(child[i].nodeType ==1) {
return true;
}
}
return false;
}
- 请编写一段 JavaScript脚本生成下面这段DOM结构。要求,使用标准的DOM方法或属性。
<div class="example">
<p class="content"></p>
</div>
<body>
<script>
var div = document.createElement('div');
var p = document.createElement('p');
div.setAttribute('class', 'example');
p.setAttribute('class', 'content');
p.innerHTML = '这里是仙女萝';
div.appendChild(p);
document.body.appendChild(div);
</script>
</body>
- 封装函数 insertAfter();功能类似 insertBefore();
<body>
<div>
<i></i>
<b></b>
<span></span>
</div>
<script>
Element.prototype.insertAfter = function(targetNode, afterNode) {
var beforeNode = afterNode.nextElementSibling;
if(beforeNode == null) {
this.appendChild(targetNode);
} else {
this.insertBefore(targetNode, beforeNode);
}
}
var div = document.getElementsByTagName('div')[0];
var i = document.getElementsByTagName('i')[0];
var b = document.getElementsByTagName('b')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
</script>
</body>
- 将目标节点内部的节点顺序逆序
example: <div><a></a><em></em></div>
<div><em></em><a></a></div>
<body>
<div>
<i></i>
<b></b>
<span></span>
</div>
<script>
var div = document.getElementsByTagName('div')[0];
Element.prototype.reverseChild = function() {
var arr = this.children;
for(let i = arr.length-1; i > 0; i --) {
// console.log(arr[i-1]);
this.appendChild(arr[i-1]);
}
}
</script>
</body>
- 计时器,到三分钟停止
<body>
minutes: <input type="text" value="0">
seconds: <input type="text" value="0">
<script>
var minutesNode = document.getElementsByTagName('input')[0];
var secondsNode = document.getElementsByTagName('input')[1];
var minutes = 0,
seconds = 0;
var timer = setInterval(function() {
seconds ++;
if(seconds === 60) {
seconds = 0;
minutes ++;
}
secondsNode.value = seconds;
minutesNode.value = minutes;
if(minutes == 3) {
clearInterval(timer);
}
}, 1000);
</script>
<body>
10 . 让小方块移动
<body>
<div style="width: 100px; height: 100px; background-color:pink;
position: absolute; left: 0; top: 0;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
function getStyle(elem, prop) {
if(window.getComputedStyle) {
return window.getComputedStyle(elem, null) [prop];
} else {
return elem.currentStyle[prop];
}
}
var timer = setInterval(function() {
div.style.left = parseInt(getStyle(div, 'left')) + 10 + 'px';
if(parseInt(div.style.left) > 500) {
clearInterval(timer);
}
}, 100)
</script>
</body>
- 使用原生js,addEventListener,给每个li元素绑定一个click事件,输出他们的顺序。
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var liCol = document.getElementsByTagName('li');
var len = liCol.length;
for(var i=0; i<len; i++) {
(function(i) {
liCol[i].addEventListener('click', function() {
console.log(i);
}, false)
}(i))
}
</script>
- 取消a标签默认事件
var a = document.getElementsByTagName('a')[0];
a.onclick = function() {
return false;
}
<a href="javascript:void(0)">demo</a>
- 小方块拖拽
<body>
<div style="width: 100px; height: 100px; background-color: orange;
position:absolute; left: 0; top: 0;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
var disX,
disY;
div.onmousedown = function(e) {
disX = e.pageX - parseInt(div.style.left);
disY = e.pageY - parseInt(div.style.top);
document.onmousemove = function (e) {
var event = e || window.event;
console.log(e.pageX + " " + e.pageY);
div.style.left = event.pageX - disX + 'px';
div.style.top = event.pageY -disY + 'px';
}
document.onmouseup = function() {
document.onmousemove = null;
}
}
</script>
</body>
<script>
// 阻止默认事件
function cancelHandler(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
// 阻止冒泡
function stopBubble(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
// 绑定事件
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if(elem.attachEvent) {
elem.attachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = handle;
}
}
// 鼠标移动时
function mouseMove(e) {
var event = e || window.event;
elem.style.left = event.clientX - disX + 'px';
elem.style.top = event.clientY - disY + 'px';
}
// 鼠标松开时
function mouseUp(e) {
var event = e || window.event;
removeEvent(document, 'mousemove', mouseMove);
removeEvent(document, 'mouseup', mouseUp);
}
// 鼠标拖拽
function drag(elem) {
var disX,
disY;
addEvent(elem, 'mousedown', function(e) {
var event = e || window.event;
disX = event.clientX - parseInt(getStyle(elem, 'left'));
disY = event.clientY - parseInt(getStyle(elem, 'top'));
addEvent(document, 'mousemove', mouseMove);
addEvent(document, 'mouseup', mouseUp);
stopBubble(event);
cancelHandler(event);
});
}
</script>
- 输入框功能完善
<input typt="text" value="请输入用户名"
style="color: #999"
onfocus="if(this.value == '请输入用户名'){this.value=''; this.style.color='#424242'}"
onblur="if(this.value == ''){this.value='请输入用户名'; this.style.color='#999'}">
- 二阶菜单栏