1.DOM初探、JS对象、XML、幻灯片案例展示
1.1.DOM/对象
Document Object Model: 文档对象模型
- DOM: 通过浏览器提供的这一套方法表示或操作HTML和XML
1.2.对象
- 本地对象(Native Object): Object Function Array String Number Boolean Error EvalError SyntaxError ReferenceError TypeError URIError Date RegExp(ECMA提供的本地对象)
- 内置对象(Built-in Object): Global(isNaN parseInt Number() decodeURI() Infinity NaN undefined) Math
本地对象和内置对象都是ECMAScript的内部对象
- 宿主对象(Host Object): window(BOM) document(DOM -> 有w3c规范)
执行JS脚本的环境提供的对象(也可以说是浏览器提供的对象), 又称浏览器对象
2.document对象、获取元素、节点、遍历树
2.1.document
IE9以下不兼容(tagname除外)
- getElementById()
- getElementsByTagName()
- getElementsByClassName()
- getElementsByName()
HTML5新引入的WEB API, IE8以下不兼容(css选择器写法),性能比getelements慢,不是实时的(具有缓存性质)不常用
- querySelector()仅返回匹配到的第一个元素
- querySelectorAll()返回匹配到的元素, 返回值是类数组
2.2.遍历节点树
节点不是元素(节点是包含元素的), 元素是节点的一部分(元素节点 = DOM元素)
- 元素节点 = 1
- 属性节点 = 2
- 文本节点(text) = 3
- 注释节点(comment) = 8
- document节点 = 9
- documentFragment = 9
- parentNode 返回某节点的父节点
- childNodes 返回包含被选节点的子节点的类数组
- firstChild 返回被选节点的第一个子节点
- lastChild 返回被选节点的最后一个子节点
- nextSibling 返回某个节点之后紧跟的节点(兄弟节点)
- previousSibling 返回某节点之前紧跟的节点(兄弟节点)
2.3.遍历元素节点树
一下这些公司中基本不用, 因为兼容性不好
- parentElement 返回指定元素的父元素 IE9+
- children 返回指定元素的子元素的集合IE7+
- childElementCount = children.length 返回指定元素的子元素的数量IE9+
- firstElementChild 返回指定的父元素的第一个子元素IE9+
- lastElementChild 返回指定的父元素的最后一个子元素IE9+
- nextElementSibling 返回指定元素的后一个兄弟元素IE9+
- previousElementSibling 返回指定元素的前一个兄弟元素IE9+
3.节点属性、方法、封装方法、DOM结构
3.1.节点属性
- nodeName 根据据节点的类型返回其名称
console.log(document.nodeName) //#document
console.log(div.nodeName) //DIV
- nodeValue 返回节点的值(属性/文本/注释节点有nodevalue), 可写
- nodeType 返回节点类型
- getAttributeNode() 从当前元素中通过名称获取属性节点
hasChildNodes() 判断某个节点下是否有子节点,返回值布尔
只有nodeType有用, 其他基本不用了解即可
3.2.封装childNode
function elementChildren(node) {
var arr = [],
children = node.childNodes;
for(var i = 0; i < children.length; i++) {
var childrenItem = children[i]
if(childrenItem.nodeType === 1) {
arr.push(childItem)
}
}
return arr
}
3.3.DOM结构
document原型继承于HTMLDocument.prototype, HTMLDocument.prototype继承于Document.prototype
- DOM结构树
4.DOM操作深入
- getElementById(): 定义在Document.prototype
- getElementsByName(): 定义在Document.prototype
- getElementsByTagName()/getElementsByClassName/querySelector/querySelectorAll: Document.prototype和Element.prototype都有
- document.body/document.head: 获取body和head标签(HTMLDocuemnt.prototype里面)
- document.title: 获取title里的文本(HTMLDocuemnt.prototype里面)
- document.documentElement: 获取HTML标签(Document.prototype里面)
4.节点创建删除、元素属性设置获取、节点属性
4.1.节点创建/删除
- document.createElement(): 通过指定名称创建一个元素(Document.prototype)
var btn = document.createElement('button')
// 此时button存在于堆内存中↑↑↑↑
btn.innerText = 'btn'
document.body.appendChild(btn)
-
document.createTextNode(‘哈哈哈’): 创建文本节点
-
document.createComment(‘注释’): 创建注释节点
-
appendChild(节点/DOM元素): 向节点的子节点列表的末尾添加新的子节点, 如果要插入的子节点已经存在,将会剪切存在节点然后插入到他的新位置
-
parent.insertBefore(a, b) 在已有的子节点前插入一个新的子节点(在父节点下的子节点b之前插入a节点)
-
parent.removeChild(子节点)从子节点列表中删除某个节点(只删除页面中的节点不会删除内存中的元素)
-
remove() 删除某个节点(内存中的也会删除)
appendChild、insertBefore、removeChild都是定义在node.prototype
- innerHTML
- innerText 老版本火狐不支持
- replaceChild(newnode, oldnode): 将某个子节点替换为另一个
4.2.元素节点的方法
- setAttribute(id, box): 创建或改变某个属性
- getAttribute(box): 通过名称获取属性的值
- dataset: 用来操作HTML元素标签的data-*属性
- document.createDocumentFragment(): 创建文档片段(碎片), 多数据时候使用
var oUl = document.getElementById('list');
vat oFrag = document.createDocumentFragment()
for(var i = 0; i < 1000; i++) {
var oLi = document.createElement('li');
oLi.innerHTML = i
oLi.className = 'list-item'
oFrag.appendChild(oLi)
}
oUl.appendChild(oFrag)
4.3.封装inserAfter
Element.prototype.insertAfter = function (target, afterNode) {
var nextElem = afterNode.nextElementSibling;
if(nextElem) {
this.insertBefore(target, nextElem)
} else {
this.appendChild(target)
}
}
5.日期对象、计时器
5.1.日期对象
var date = new Date()
- getDate(): 获取当前天
- getDaty(): 获取周几(0是周日)
Date.prototype.getWeekDay = function(lang) {
var day = this.getDay()
switch(day) {
case 0:
return lang == 'chs' ? '星期天' : 'Sunday';
break;
case 1:
return lang == 'chs' ? '星期一' : 'Monday';
break;
case 2:
return lang == 'chs' ? '星期二' : 'Tuesday';
break;
case 3:
return lang == 'chs' ? '星期三' : 'Wednesday';
break;
case 4:
return lang == 'chs' ? '星期四' : 'Thursday';
break;
case 5:
return lang == 'chs' ? '星期五' : 'Friday';
break;
case 6:
return lang == 'chs' ? '星期六' : 'Saturday';
break;
}
}
- getMonth(): 获取当前月(0-11需要加1)
- getFullYear(): 获取当前年
- getHours() 获取小时
- getMinutes() 获取分钟
- getSeconds() 获取秒
- getMilliseconds() 获取毫秒
- getTime() 返回1970年1月1日0点0分0秒至今的毫秒数
// 时间戳转时间
var date = new Date(1527782400000),
year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate();
console.log(year + '-' + month + '-' + day);
5.2 计时器/定时器
window下的方法
//返回值是定时器的唯一标识
var timer1 = setInterval(function(){}, 1000)//1
var timer2 = setTimeout(function(){}, 1000)//2
6.数学取整方法
6.1.数学取整
- Math.round()四舍五入(除开负数.5)
- Math.ceil()向上取整/向大取整
- Math.floor()向下取整/向小取整
7.滚动距离与高度、兼容模式、可视尺寸
7.1.滚动距离
-
window.pageXOffset/pageYOffset(IE9及以上), 常规写法
-
document.body.scrollLeft/scrollTop
-
document.documentElement.scrollLeft/scrollTop
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fQVmQPuB-1644460390068)(C:\Users\lengr\Desktop\学习\images\Snipaste_2022-02-09_10-00-47.png)]
//兼容滚动条距离封装
function getScrollOffset() {
if(window.pageXOffset) {
return {
left: window.pageXOffset,
top: window.pageYOffset
}
} else {
return {
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
7.2.浏览器的怪异模式和标准模式
加了就是标准模式,不加就是怪异模式
document.compatMode返回当前模式
- BackCompat怪异
- CSS1Compat标准
7.3.可视尺寸(浏览器页面可视宽高)
- window.innerWidth/innerHeight 常规方法IE9+
- document.documentElement.clientWidth/clientHeight IE9及以下
- document.body.clientWidth/clientHeight 怪异模式
// 兼容可视尺寸封装
function getViewportSize() {
if (window.innerWidth) {
return {
width: window.innerWidth,
height: window.innerHeight
}
} else {
if (document.compatMode === 'BackCompat') {
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
}
7.4.浏览器宽高
- document.body.scrollHeight/scrollWidth 常用
- document.documentElement.scrollHeight/scrollWidth
// 兼容封装
function getScrollSize() {
if(document.body.scrollWidth) {
return {
with: document.body.scrollWidth,
height: document.body.scrollHeight
}
} else {
return {
with: document.documentElement.scrollWidth,
height: document.documentElement.scrollHeight
}
}
}
- getBoundingClientRect()返回元素的大小及其相对于视口的位置
- offsetTop/offsetLeft 返回距离有定位的父级距离(父级无定位继续向外查找)
- offsetParent 返回最近一个父元素
function getElementDocPosition(e) {
var parent = e.offsetParent,
offsetLeft = e.offsetLeft,
offsetTop = e.offsetTop;
while(parent) {
offsetLeft += parent.offsetLeft;
offsetTop += parent.offsetTop;
parent += parent.offsetParent
}
return {
left: offsetLeft,
top: offsetTop
}
}
7.5.操作滚动条
- window.scroll(x, y)滚动到文档中的某个坐标
- window.scrollTo(x, y)滚动到文档中的某个坐标
- window.scrollBy(x, y)按指定的偏移量滚动文档
8.读写样式属性、操作伪元素、元素运动初探
8.1.属性样式读写
- window.getComputedStyle(element, null): 返回值是 CSSStyleDeclaration 类型的对象(当前标签下所有的样式) IE9+, null可以填伪元素字符串(‘affter’)
- div.currentStyle IE9以下但是chrome没有
// 兼容封装
function getStyles(e, prop) {
if(window.getComputedStyle){
if(prop) {
return window.getComputedStyle(e, null)[prop]
} else {
return window.getComputedStyle(e, null)
}
} else {
if(prop) {
return e.currentStyle[prop]
} else {
return e.currentStyle
}
}
}
- HTMLElement.offsetWidth 返回一个元素的布局宽度(width,padding,border)
- HTMLElement.offsetHeight 返回一个元素的布局高度(width,padding,border)
9.事件处理函数、冒泡捕获、阻止冒泡默认事件
9.1事件
- element.onclick: 最原始的事件绑定方法, 全部都可以兼容,但是同一元素只能绑定一个事件,如果继续绑定则会覆盖之前的
- : 内联事件, 不推荐使用
-
- element.addEventListener(‘event’, fn, false): 事件类型,事件处理函数,事件执行阶段(false默认冒泡阶段执行, true捕获阶段执行),IE9+ W3C规范, 同一元素可以绑定多个
oBtn.addEventListener('click', function() {
this.innerHTML = 'asd'
})
oBtn.addEventListener('click', function () {
console.log('asd');
})
//事件兼容封装
function addEvent(el, type, fn) {
if (el.addEventListener) {
el.addEventListener(type, fn);
} else if (el.attachEvent) {
el.attachEvent('on' + type, function() {
fn.call(el);
})
} else {
el['on' + type] = fn;
}
}
- element.removeEventListener: 移除事件(arguments.callee)
- element.onclick = null: 移除事件
9.2事件冒泡
一层一层的向上传递事件的现象就是冒泡
<div class="wrapper">
<div class="outer">
<div class="inner"></div>
</div>
</div>
var wrapper = document.getElementsByClassName('wrapper')[0],
outer = document.getElementsByClassName('outer')[0],
inner = document.getElementsByClassName('inner')[0];
wrapper.addEventListener('click', function () {
console.log('1--wrapper');
}, false)
outer.addEventListener('click', function () {
console.log('2--outer');
}, false)
inner.addEventListener('click', function () {
console.log('3--inner');
}, false)
9.3事件捕获
在捕获的过程中,最外层(根)元素的事件先被触发,然后依次向内执行,直到触发最里面的元素(事件源)
var wrapper = document.getElementsByClassName('wrapper')[0],
outer = document.getElementsByClassName('outer')[0],
inner = document.getElementsByClassName('inner')[0];
wrapper.addEventListener('click', function () {
console.log('1--wrapper');
}, true)
outer.addEventListener('click', function () {
console.log('2--outer');
}, true)
inner.addEventListener('click', function () {
console.log('3--inner');
}, true)
先捕获 后冒泡
9.4阻止冒泡/默认事件
- e.stopPropagation(): w3c推荐阻止冒泡
- e.cancelBubble = true: IE的
- e.preventDefault(): w3c推荐阻止默认事件
- e.returnValue = false: IE
// 封装兼容取消冒泡
function cancelBubble(e) {
var e = e || window.event;
if(e.stopPropagation) {
e.stopPropagation;
} else {
e.cancelBubble = true;
}
}
10.冒泡捕获流、事件与事件源对象、事件委托
10.1事件源
事件源:事件捕获阶段、处于目标阶段、事件冒泡阶段
10.2事件对象
- target/srcElement:事件源对象
10.3事件委托/事件代理
<button>增加</button>
<ul>
<li>1</li>
<li>2</li>
<ul>
var oList = document.getElementByTagName('ul')[0],
oLi = oList.document.getElementByTagName('li'),
oBtn = document.getElementByTagName('button')[0];
oList.onclick = function(e) {
var e = e || window.event,
tar = e.target || e.srcElement;
console.log(tar.innerText)
// 拿到li下标
var index = Array.prototype.indexOf.call(oLi, tar)
console.log(tar.index)
}
oBtn.onclick = function() {
var li = document.createElement('li');
li.innerText = oList.length + 1;
oList.appendChild(li)
}