随时更新的知识点
2019-07-31
弹窗可以通过 open(url, name, params) 调用。它返回新窗口的引用
- name相同将替换窗口链接,这可以实现webpack总是打开一个窗口调试,同时可以通过返回的窗口引用关闭窗口。
2019-07-16
mouseover/out和mouseenter/leave的区别和共同点
- 共同点:mouseover/out、mouseenter/leave事件有一个额外的目标:relatedTarget,作为起点/终点的元素,是对target的补充
- 不同点:
- mouseover/out即使从父元素转到子元素时也会被触发,假设鼠标一次只会移入一个元素,能冒泡
- mouseenter/leave鼠标进入子元素也不会被触发,只关注鼠标在整个元素的内部还是外部,不会冒泡
性能优化
- 长图文中,可将真实图片放入data-src中,src使用加载图,然后监听滚动事件,检查图片元素是否出现在可视范围内(elem.getBoundingClientRect()),出现则用data-src替换src
async和defer属性的异同
- 相同点
- 不同点
- async 加载优先,先加载完先执行,与DOMContentLoaded无关
- defer 文档顺序,排在前面先执行,在DOMContentLoaded之前在文档加载解析之后执行
如何防止滚动
- 阻止whell事件
- 阻止pageUp、pageDown的keydown事件
- 不能在onscroll监听者中通过event.preventDefault()来阻止滚动,因为它在滚动事件发生之后才出发
2019-07-15
单击事件which属性
- event.which == 1 —— 左按钮
- event.which == 2 —— 中间按钮
- event.which == 3 —— 右按钮
在Mac上通常使用cmd而不是Ctrl
- 在Mac上左击+Ctrl会被解释为右击,会生成contextmenu事件
- 如果想让所有系统用户感到舒适,应该和CtrlKey一起使用metaKey,对于js意味着应该检查
if (event.ctrlKey || event.metaKey)
如何阻止双击选择文本
- 文本选择是mousedown事件的默认浏览器操作,比较好的解决方案是处理mousedown并阻止他发生
- 使用 getSelection().removeAllRanges() 取消选择后的内容
- CSS 属性 user-select:none(带有浏览器前缀)完全禁用文本选择
2019-07-12
各个尺寸代表的含义

- offsetParent:最近的祖先元素
- CSS定位(position为absolute、relative或fixed)
<td>
、<th>
、<table>
<body>
- offsetLeft/offsetTop:当前元素左上角相对于 offsetParent 节点的左/上边界偏移的像素值
- offsetWidth/offsetHeight:元素的“外部”宽度/高度,它的完整大小包括边框、内边距、内容、滚动条(如果存在的话)
- clientLeft/clientTop:内测和外侧的相对坐标,约等于边框,但当出现滚动条在左侧时,包含滚动条的宽度
- clientWidth/clientHeight:元素边框内区域的大小,包括内边距、内容,不包括滚动条
- scrollLeft/scrollTop:元素隐藏、滚动部分的宽度/高度,相对于client,可修改,将 scrollTop 设置为 0 或 Infinity 将使元素分别滚动到顶部/底部
- scrollWidth/scrollHeight:内容的实际宽高
getComputedStyle(elem).width 与 elem.clientWidth 的区别
- clientWidth的值是数值,getComputedStyle(elem).width返回一个包含px的字符串
- getComputedStyle(elem)可能返回非数值的结果,比如auto
- clientWidth是元素的内容区域加上内间距,而CSS宽度(具有标准的box-sizing)是内部不包括内间距的空间区域
- clientWidth总是不包括滚动条的宽度
window相关尺寸和滚动
- 获取窗口的宽高使用document.documentElement.clientWidth/Height,不使用window.innerWidth/Height,因为后者包含滚动条
- 文档的宽度高度使用Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight)
- 文档的滚动位置,由于bug(157855,106133),部分情况下需使用document.body代替document.documentElement来获取scrollLeft/Top属性,同时可以使用window.pageXOffset/pageYOffset代替
- 滚动页面可以通过修改document.documentElement.scrollTop/Left的值来实现,但由于上面bug的原因,部分需要修改document.body.scrollTop/Left,更好的解决方案是window.scrollBy(x, y)和window.scrollTo(pageX, pageY)
- 使用element.scrollIntoView(top)使元素出现在窗口顶部(top=true)或底部(top=false)
- 使用document.body.style.overflow = "hidden"禁止文档滚动,使用document.body.style.overflow = "" 恢复滚动,滚动条的消失带来的页面变化的情况可以通过对比前后clientWidth,将对应的padding值添加到document.body中取代滚动条以保持页面内容宽度
事件奇技
- 尽量避免使用阻止冒泡,使用其他方法替代
- 如果默认动作被阻止,event.defaultPrevented的值会变成true,可以利用这个特性从上次判断这个属性来模拟组织冒泡
2019-07-11
- 将 scrollTop 设置为 0 或 Infinity 将使元素分别滚动到顶部/底部
2019-07-10
DOM属性和HTML特性
- DOM属性
- DOM上的属性和方法就像标准的JavaScript对象
- 值并不只是字符串
- HTML特性
- 浏览器读取HTML文本并根据标签生成DOM对象,它会辨别标准化特性然后以此创建DOM属性
- 不区分大小写
- 值只能是字符串
- 相关方法
- removeAttribute():删除属性
- setAttribute():写入某个属性值
- getAttribute():读取某个属性的值
- getAttributeNames():返回当前元素的所有属性名
- hasAttribute():某个属性是否存在
- hasAttributes():当前元素是否有属性
- elem.attributes:获取所有特性,是个NamedNodeMap类型的值
- 属性-特性的同步
- 当一个标准化的特性被改变,相应的属性随之改变,反之亦然
- input.value只能从特性同步到属性,反之不行,即通过setAttribute('value', 'value')可以改变input.value的值,反过来不行
操作DOM
- 创建节点的方法:
- document.createElement(tag) —— 用给定标签创建一个节点,
- document.createTextNode(value) —— 创建一个文本节点(很少使用),
- elem.cloneNode(deep) —— 如果参数 deep==true 将元素及后代子元素进行克隆。
- 插入和移除节点的方法:(这些方法都返回 node)
- 从 parent
- parent.appendChild(node)
- parent.insertBefore(node, nextSibling)
- parent.removeChild(node)
- parent.replaceChild(newElem, node)
- 添加一些节点和字符串:
- node.append(...nodes or strings) —— 在 node 末尾位置增加,
- node.prepend(...nodes or strings) —— 在 node开头位置增加 ,
- node.before(...nodes or strings) —— 在 node 之前位置增加,
- node.after(...nodes or strings) —— 在 node 之后位置增加,
- node.replaceWith(...nodes or strings) —— 替换 node。
- node.remove() —— 移除 node。
- 在 HTML 中添加内容 elem.insertAdjacentHTML(where, html),在 where 位置进行操作:
- "beforebegin" —— 将 html 插入 elem 到开头的前面位置,
- "afterbegin" —— 将 html 插入 elem 到开头的后面位置,
- "beforeend" —— 将 html 插入 elem 到结尾的前面位置,
- "afterend" —— 将 html 插入 elem 到结尾的后面位置。
所有插入操作都会从节点原来的位置把节点移除,所以如果想要移动一个元素到另一个地方,不需要移除旧的元素
elem.insertAdjacentText 和 elem.insertAdjacentElement 跟 elem.insertAdjacentHTML 很相似,只不过他们一个用来插入字符串,一个用来插入元素,但是很少使用这两个方法。
样式和类
- class
- className
- classList
- .add
- .remove
- .toggle
- .contains
- style
- 对于多单词,使用 camelCase,即-x变成X(z-index -> zIndex, -moz-border-radius -> MozBorderRadius)
- 将某个样式置为空字符串,浏览器一般会应用CSS类以及内置样式,就像根本没有这样的style属性
- 用style.cssText进行重写样式,效果类似于 setAttribute('style', '...')
- 样式值中必须附上CSS单位
- style属性仅对style属性值进行操作,而不是任何CSS级联,因此不能使用element.style来读取来自CSS类的任何内容
- getComputedStyle
- 返回的是属性的解析值
- 需要完整的属性名,像padding这种值会存在浏览器差异,正确的方式是获取paddingTop等值
2019-07-09
关于innerHTML
- 功能拆解
- 移除旧的内容
- 新的innerHTML被书写(旧的和新的相连接)
- 特点
- 因为内容“零输出”并且被从头重写,所有的图片和其他资源都会被重新加载
关于outerHTML
- outerHTML属性包含元素的完整HTML,就像是innerHTML加上元素本身
- 写入到outerHTML后不会改变元素,而是作为一个整体替代了它
- 旧的内容仍可通过element.outerHTML取到,新的内容需通过查询DOM来获取引用
2019-07-08
- 空格和换行符是完全有效的字符,它们形成文本节点并成为DOM的一部分,但有2个顶级排除项目
- 由于历史原因,
<head>
之前的空格和换行符被忽略
- 如果在
</body>
之后放置了一些东西,它会自动移到body内部,因为HTML规范要求所有内容必须位于body内,所以后面没有空格
DOM 集合的特点
parentElement和parentNode的区别
大部分情况下没有区别,只有document.documentElement.parentNode === document,而document.documentElement.parnetElement === null,原因是document不是元素节点
DOM节点搜索总结
| Method | Searches by... | Can call on an element | Live? |
| - | - | - | - |
| getElementById | id | - | - |
| getElementsByName | name | - | ✔ |
| getElementsByTagName | tag or '*' | ✔ | ✔ |
| getElementsByClassName | class | ✔ | ✔ |
| querySelector | CSS-selector | ✔ | - |
| querySelectorAll | CSS-selector | ✔ | - |
2019-07-05
模块相比普通脚本的区别
- 始终使用"use strict"
- 模块级作用域,即每个模块都有自己的顶级作用域
- 模块代码仅在第一次导入时解析
- import.meta对象包含当前模块的一些信息
- 顶级"this"是undefined
特定于浏览器的功能
- 模块脚本是延迟解析的,就和defer属性一样
- 不会阻塞HTML的解析,与其他资源并行加载
- 直到HTML文档完全解析渲染后模块脚本才开始执行
- 执行脚本的相对顺序:前面的先执行
- 内联脚本是异步的,内联脚本和外部脚本都允许使用