DOM 基础 api
这方面的文章非常多,也没什么难度,建议阅读总结 js 常用的 dom 操作
DOM 样式获取与修改
- element.style 只能获取到行内样式,但是可以修改
- element.currentStyle 和 window.getComputedStyle (element)不能修改,但是可以获取非行内样式
- getComputedStyle 兼容谷歌和火狐不兼容 ie<9,currentStyle 则相反,主要在低版本 IE 上使用
// 兼容写法
export const getStyle = (ele, attr) => {
if (window.getComputedStyle) {
return window.getComputedStyle(ele, null)[attr];
}
return ele.currentStyle[attr];
};
get 与 query 的差别
document.getElementById('test');
document.querySelector('#test');
不同之处在于:
- getXxxByXxx 选出的元素是动态的(获取 dom 后再对 dom 操作会影响已获取的 dom),querySelectorAll 是静态的
- getElementsByXxx 返回的是 HTMLCollection,querySelectorAll 返回的是 NodeList
<div id="parent">
<div class="son">1</div>
</div>
<script>
// 下面代码可以很明显的看出来区别
(function diffQueryAndGetBy() {
let parent = document.querySelector('#parent');
let div = document.createElement('div');
// 注意顺序, query等于是在这个位置做了一个快照
let querySon = document.querySelectorAll('.son');
let getSon = document.getElementsByClassName('son');
div.className = 'son';
parent.appendChild(div);
console.log('querySon: ', querySon);
console.log('getSon: ', getSon);
})();
</script>
从控制台可以看出来分别返回的 nodeList 和 HtmlCollection,好奇心迫使我进一步了解这两玩意的区别。
NodeList 和 HTMLCollection 的异同
它们都是类数组,有 length 属性,都是动态的;
HTMLCollection 只有 element,NodeList 包含元素和其他节点(注释,文本等)。
HTMLCollection多了一个namedItem()方法,通过标签的name属性来获取dom的引用
Node 是一个基础类型,document, element, text, comment, DocumentFragment 等都继承于 Node.
DOM 的长宽属性
- clientWidth/Height = content + padding
- offsetWidth/Height = content + padding + border
- scrollWidth/Height: 实际的宽高
- clientLeft/Top = borderLeft/Top
- offsetLeft/Top = border 相对于第一个具有定位属性且不为 static 的祖先元素的距离
- scrollTop/Left: dom 超出的宽高
注意盒子类型,content-box:width = content; border-box: width = content+padding+border
事件的距离属性
- clientX/Y: 相对于窗口的左上角
- screenX/Y: 相对于设备的左上角
- offsetX/Y: 相对于点击 dom 的 content 的左上角 (火狐为 layerX 和 layerY)
- pageX/pageY: 相对于
整个页面
,一般与 clientX/Y 一样,但是当整个页面出现滚动条时会大于 clientX/Y
事件流
DOM0 级事件,内联模型和脚本模型,即行内绑定和动态绑定事件,如下:
// 内联模型
<button onclick="handleClick()"></button>;
// 脚本模型
var btn = document.getElementById('btn');
btn.onclick = function () {};
DOM0 级只支持冒泡阶段
ECMAScript 进一步规范,有了 DOM2 级事件处理程序,addEventListener()和 removeEventListener()。其中 addEventListener(eventName, fnName, true/false), true 为捕获阶段触发,false 为冒泡阶段触发。值得注意的是,对于同一个元素不区分冒泡还是捕获,按照绑定顺序执行
。
DOM2 级事件规定的事件流包括三个阶段:
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
阻止事件冒泡,e.stopPropgation(); 阻止默认行为,e.preventDefault();
自定义事件
const event = new Event('event_name')
ele.addEventListener('event_name',fn,xx)
ele.dispatch(event)
如果想要传递自定义数据,使用 new CustomEvent(‘event_name’, {detail: xxx, bubbles: true}),bubbles 为 true 可以冒泡。