参考来源:
JavaScript权威指南: book.douban.com/subject/105…
JavaScript高级程序设计: book.douban.com/subject/105…
千古壹号: github.com/qianguyihao…
现代JavaScript教程: zh.javascript.info/
BOM
- navigator对象提供有关浏览器和操作系统的背景信息.
- lacation对象允许我们读取当前url并将浏览器重定向到新的url
间歇调用和超时调用
javascript是单线程语言, 因此一定时间内只能执行一段代码, 为了控制要执行的代码, 就要有一个javascript任务队列. setTimeout()的第二个参数告诉javascript再过多长时间把当前任务添加到执行队列中去. 如果队列是空的, 则添加的代码立即执行, 不是空的就要等前面的代码执行完了再执行.
// 设置超时调用
let timeoutId = setTimeout(function(){alert("hey, world");}, 1000);
// 取消尚未执行的调用
clearTimeout(timeoutId);
// 间歇调用
let num = 0, let max = 10;
let intervalId = null;
function fun(){
num++;
if(num === max){clearInterval(intervalId);alert("Done");}
}
intervalId = setInterval(fun, 500);
复制代码
DOM
Document Object Model文档对象模型是针对HTML和XHTML的一个API.
DOM描绘了一个层次化的节点树, 允许开发人员添加, 移除和修改页面的某一部分.
文档元素是文档的最外层元素, 文档中的其他所有元素都包含在文档元素中. 每个文档只能有一个文档元素. 在HTML中, 文档元素始终是html
如果我们在/body之后放置了一些东西, 比如script标签, 那么它会自动移动到body内部
- document.documentElement始终指向HTML页面中的html元素
- document.body直接指向body元素
- document.title属性值是title元素中的文本
- document.head
节点Node
除了IE之外, 在其他所有浏览器中都可以访问到这个类型. JavaScript中所有节点类型都继承Node类型
if(someNode.nodeType === Node.ELEMENT_NODE){ // 在IE中无效
alert("Node is an element!");
}
if(someNode.nodeType === 1){} // 适用于所有浏览器
复制代码
对于元素节点, nodeName中保存的始终是元素的标签名, 而nodeValue的值始终是null
- 每个节点都有一个childNodes属性, 其中保存着一个NodeList对象. NodeList对象的独特之处在于, 它实际上是基于DOM结构动态执行查询的结果
- 每个节点都有一个parentNode属性, 该属性指向文档树中的父节点. 包含在childNodes列表中的所有节点都具有相同的父节点.
- 通过使用previousSibling和nextSibling属性, 可以访问同一列表中的其他节点. 列表中第一个节点的previousSibling属性值为null
- 父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点
let first = someNode.childNodes[0];
let second = someNode.childNodes.item(1);
let length = someNode.childNodes.length;
复制代码
hasChildNodes()在节点有子节点的情况下返回true, 没有子节点返回false.
所有节点都有一个属性ownerDocument, 该属性指向表示整个文档的文档节点
元素节点
- children
- firstElementChild
- lastElementChild
- previousElementSibling
- nextElementSibling
- parentElement
innerHTML允许将元素中的html作为字符串来获取和修改. 如果innerHTML将script标签插入到dom中, 此时script不会执行
outerHTML只能读取, 不能修改, 它包括自己本身的标签
elem.contains(elem2)判断elem2是否是elem的子节点 elem.cloest(".fa")匹配选择器是fa且距离elem最近的祖先元素
elem.hidden = true 和css中的display:none相似
elem.textContent: 标签内的文本
elem.style.borderTopWidth: 驼峰命名
包括padding, 但不包括border, 滚动条
- elem.clientWidth
- elem.clientHeight
- elem.clientLeft
- elem.clientTop
包括padding, border, 滚动条
- elem.offsetWidth
- elem.offsetHeight
当子元素比父元素高且overflow=scroll时, scrollHeight大于clientHeight
- elem.scrollWidth
- elem.scrollHeight
dataset
<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>John Doe
</div>
<script>
var el = document.querySelector('#user');
// el.dataset.id === '1234567890'
// el.dataset.user === 'johndoe'
// el.dataset.dateOfBirth === ''
el.dataset.dateOfBirth = '1960-10-03';
</script>
复制代码
操作节点
创建节点: document.createElement("li")
插入
- appendChild(): 用于向childNodes列表末尾添加一个节点, 返回新增的节点. 如果传入appendChild()中的节点已经是文档的一部分了, 那结果就是将该节点从原来的位置转移到新位置.
- insertBefore(): 接受两个参数, 要插入的节点和作为参照的节点. 插入节点后, 被插入的节点会变成参照节点的前一个同胞节点.
删除
- replaceChild(): 接受的两个参数是: 要插入的节点和要替换的节点
- removeChild()移除节点
操作css类
- elem.classList.add()
- elem.classList.remove()
- elem.classList.toggle()
cloneNode()用于创建调用这个方法的节点的副本, 接受一个布尔值参数, 表示是否执行深复制. 深复制即复制节点及其子节点树, 浅复制即只复制节点本身
节点的特性
elem.attributes // 所有特性的集合
elem.hasAttribute()
elem.getAttribute("color")
elem.setAttribute("color", "red")
elem.removeAttribute()
复制代码
查找元素 所有的getElementsBy方法返回一个live集合, 可以自动更新 querySelectorAll会返回一个static集合, 固定不变
// 如果元素有id属性, 那么该id也会有一个同名的全局变量
let btn = document.getElementById("btn");
let img0 = document.getElementsByTagName("img")[0];
let radios = document.getElementsByName("color");
let div = document.getElementsByClassName("container");
复制代码
事件Event
事件: 就是文档或浏览器窗口中发生的一些特定的交互瞬间. 可以使用处理程序来预定事件, 以便事件发生时执行相应的代码.
let btn = document.getElementById("btn");
btn.ondblclick = function(event){
console.log(event.type); // 打印"click"
}
复制代码
常使用到的事件如下
事件类型
鼠标事件
- click
- dblclick双击
- contentmenu右击
- mouseover/mouseout光标在元素上移入移出
- mouseenter/mouseleave光标移入移出, 不会冒泡
- mousedown/mouseup单击/释放任意鼠标按钮
- mousemove
- copy复制文本事件
event.which === 1 左按钮 event.which === 2 中间按钮 event.which === 3 右按钮
鼠标事件的两种坐标
- 对于窗口而言, clientX/clientY
- 对于文档而言, pageX/pageY
表单元素事件
- submit
- focus获得焦点, 不会冒泡
- blur失去焦点, 不会冒泡
- focusin获得焦点, 冒泡
- focusout失去焦点, 不冒泡
键盘事件
- keyup
- keydown
css动画事件
- transitioned
事件回调函数
- elem.onclick = ()=>{}
- elem.addEventListener('click', ()=>{}, true)
- elem.removeEventListener()移除处理器
addEventListener
- 参数1: 事件名
- 参数2: 回调函数
- 参数3: true表示事件捕获阶段触发, false表示事件冒泡阶段触发(默认)
使用on*方法不能为一个事件分发多个处理器, 如果我们想分发多个处理器, 应该使用addEventListener. 有一些事件处理器只能通过addEventListener设置, 比如transitioned事件
事件对象
当事件发生时, 浏览器会创建一个事件对象, 将信息放入其中, 并将其作为参数传入处理器.
event属性
- event.type: 事件类型, 比如'click'
- event.currentTarget: 处理事件的元素
- event.clientX/event.clientY: 鼠标事件中光标相对于窗口的坐标
冒泡和捕获
事件流: 在单击按钮的同时, 你也单击了按钮的容器元素, 甚至也单击了整个页面. 事件流描述的是从页面中接收事件的顺序.
事件冒泡: 当事件发生在元素上, 它首先会运行元素本身的处理器, 然后运行父元素上的, 再然后是其他祖先上的
阻止冒泡
- event.stopPropagation(): 一个事件处理器停止冒泡
- event.stopImmediatePropagation(): 停止事件冒泡并阻止当前元素上的处理器运行
- IE10以下: event.cancelBubble = true
事件捕获: 不太具体的节点应该更早接收到事件, 而最具体的节点应该最后接收到事件.
事件委托: 把一个元素响应事件的回调函数委托到另一个元素上. 例如把点击事件绑定到ul标签上, 然后在执行事件的时候判断目标元素是哪一个li.
事件委托的好处和局限性:
- 简化初始化并节省内存, 不需要添加许多处理器
- 事件必须要冒泡
浏览器默认动作
许多事件会自动触发浏览器动作
- 单击一个链接
- 单击一个表单提交按钮
- 选中文本
阻止浏览器默认事件
- event.preventDefault()
- 如果使用onclick分发处理器, 只需on*内部返回false