第一板块
DOM渲染原理
DOM元素选择器语法注意
获取单个元素
let box = document.querySelector('.box')
- 如果选择器存在,则获取
DOM对象 - 如果选择器不存在,则获取
null注意:唯一一个产生null的语法(一般为选择器写错)
获取多个元素
let boxList = document.querySelectorAll('.box')
- 如果选择器存在,则获取
伪数组(伪数组:有数组三要素{下标、元素、长度},但没有数组方法) - 如果选择器不存在,则获取
空数组
区别
- document.querySelector 获取dom对象,可以直接修改DOM树
- document.querySelectorAll 获取伪数组,不可以直接修改DOM树,必须要先通过下标取出dom对象之后,才可以修改dom树
innerText 与 innerHTML
元素.innerText : 获取元素文本
元素.innerHTML : 获取元素内容(文本+标签)
innerText和innerHTML异同点
相同: 都是获取字符串
不同: 获取内容不同
innerText : 获取文本,无法解析字符串的标签
innerHTML : 获取内容, 可以解析字符串的标签
操作元素类名
元素.className:通过类名可以修改多个样式,但是会覆盖原先的类样式
classList语法: 操作类名,但是不会覆盖原来的类名
- 新增类名 : 元素.classList.add('类名')
- 移除类名 : 元素.classList.remove('类名')
- 切换类名 : 元素.classList.toggle('类名')(切换: 有则移除,无则新增)
- 判断类名 : 元素.classList.contains('类名')(获取布尔值,true:有类名 false:没有)
表单几个布尔类型属性
- disabled:是否禁用
- checked:是否选中(radio,checkbox)
- selected:是否选中(用在option)
事件及注册事件
事件三要素(用于分析需求思路)
- 事件源:什么元素
- 事件类型:什么时候(鼠标单击、双击、移入、移出)
- 事件处理函数:做什么事情
事件工作原理 :
- 注册事件 : 本质是给对象添加方法, 函数在声明的时候不会立即执行的。(声明函数)
- 触发事件 : 点击元素的时候,浏览器会自动捕捉到交互。 主动帮我们调用这个事件的方法。(调用函数)
注意
-
js命名规则和css命名规则是不一样的:js中css中的带 - 的属性都需要转成小驼峰命名
-
bug分析 原因:元素选择器括号中没有点,默认对标签进行选择,得到结果为null
-
对样式设置空字符串,会自动加载默认样式
-
获取body的两种方式
- 根据选择器获取: document.querySelector('body')
- body是唯一的: document.body
-
注意修改元素的样式时,都需要
元素.style -
键盘输入事件类型 : oninput
-
获取文本域长度 : area.value.length
-
从表单标签中拿到文本用
元素.value,而不是用元素.innerText
第二板块
排他思想(多个元素,只选一个)
- 循环排他(炸弹):先循环干掉所有元素,再复活自己
- 类名排他(狙击枪):先通过类名干掉选中的元素,再复活自己
开关思想(判断是否存在特殊元素)
- 声明开关变量:一般默认值为true
- 遍历数组:检查开关是否成立,如果不成立则修改开关变量为false,并结束循环
- 获取开关变量
常用鼠标事件
- mousedown,鼠标按下时触发
- mouseup,鼠标抬起时触发
- mousemove,鼠标移动时触发
- mouseenter,鼠标移入时触发(不冒泡)
- mouseleave,鼠标移除时触发(不冒泡)
- mouseover,鼠标移入时触发(冒泡)
- mouseout,鼠标移出时触发(冒泡)
常用键盘事件
- keyup:释放某个键盘键时触发
- keydown:在键盘上按下某个键时触发(对任意键有效)
- keypress:按下某个键盘键并释放时触发(只对字符串有效) 注意:如果只想读取字符, 用KeyPress, 如果想读各键的状态, 用KeyDown
注意
-
交集选择器
li.active表示li标签中的active类名(做加强版选择器) -
js这块多写注释,先写需求或思路分析,在代码部分分块解释代码(前期保证书写思路清晰)
-
当需要做布尔判断时
第三板块
自定义属性
操作自定义属性(html本来没有的属性,用于存储数据)
- 设置属性:元素.setAttribute('属性名',属性值)
- 获取属性:元素.getAttribute('属性名')
- 移除属性:元素.removeAttribute('属性名')
节点
由四个部分组成:元素节点、属性节点、文本节点、注释节点
作用:帮助渲染引擎更好的渲染DOM树
注意只有元素节点才会子节点
dom树的三种新增方式
document.write():几乎不用元素.innerHTML:少用(如果一次性操作超过100个以上元素,存在性能问题)document.createElement():DOM推荐使用
date对象
定时器
- 开启永久定时器:
let timeID = setInterval(function(){}, 间隔时间) - 开启一次性定时器:
let timeID = setTimeout(function(){}, 间隔时间) - 清除定时器:
clearInterval(timeID)
定时器ID:定时器的返回值为定时器的ID
注意
-
标签设置属性
display = 'none',元素在DOM树中依然存在;如果用元素.removeChild(子元素),元素在DOM树中不存在 -
回调函数:如果一个函数的参数也是函数,则这个参数叫做回调函数
第四板块
事件监听
元素.removeEventlistener只能移除具名事件,无法移除匿名事件
事件阻止
- 在html中,有少部分的标签自带默认点击事件:a form
- 如果要给这两个标签注册点击事件,并且不自动跳转,需要阻止他们的默认事件
- 通过在注册事件中设置
e.preventDefault()实现阻止
事件对象
存储与事件触发相关数据
当触发事件的时候,浏览器会自动捕捉触发相关的数据(鼠标、键盘),会自动存入对象中,叫做事件对象
通过给事件处理函数添加形参
找bug思路
1.js所有的bug分为两种
1.1 语法错误 : Syntax Error
1.2 数据错误 : Type Error
* TypeError : 一般是你某个数据是undefined或者null导致
* null : 获取元素选择器写错
* undefined :
* Reference Error : 声明变量和使用不是同一个单词(变量声明)
原因: CPU解析代码做两件事: 识别语法,处理(运算和存储)数据
2.不报错bug
* 主要原因是因为: js中的引用类型可以动态新增数据
* 给自己心里大方向案例: 绝壁是单词写错
获取用户按键
事件冒泡
当触发子元素的事件,所有父级元素“同名事件”依次触发 冒泡顺序:子元素 >父元素 >body >html >document window
事件捕获
当触发子元素的事件,所有父级元素“同名事件”依次触发(冒泡顺序与冒泡相反) 只有唯一的方式可以注册捕获事件:addEventListener()第三个参数为true
事件流
- 事件捕获
- 事件目标
- 事件冒泡
用
e.eventPhase拿到事件流阶段
事件委托(给父元素注册事件,委托给子元素处理)
事件委托底层原理:事件冒泡 事件委托应用:给动态新增元素注册事件 注意:
- 动态新增元素无法直接注册事件,因为这些元素一开始在页面并不存在,无法获取。
- 不能使用this:this代表事件源,指向父元素
- 需要使用e.target :事件目标(用户到底点击的是哪一个li元素,触发的这个冒泡)
常见事件对象
获取鼠标出发点(到页面左上角距离):e.pageX/e.pageY
获取按键字符串:e.key
获取按键ASCII码:e.keyCode
事件目标(触发本次冒泡的子元素):e.target
阻止form和a默认事件:e.preventDefault
阻止事件流:e.stopPropagar
注意
字符串的大小比较:是将字符串转换成ASCII码对应的数字大小进行比较
事件委托的父元素不能是新增的,如果开发中找不到准确的父元素,直接给body注册
第五板块
三大家族
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>标题</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 150px;
height: 150px;
background-color: pink;
overflow: auto;
padding: 10px;
border: 10px solid red;
margin: 100px;
}
</style>
</head>
<body>
<div class="box">
我有很多很多的内容哦 我有很多很多的内容哦 我有很多很多的内容哦
我有很多很多的内容哦 我有很多很多的内容哦 我有很多很多的内容哦
我有很多很多的内容哦 我有很多很多的内容哦 我有很多很多的内容哦
我有很多很多的内容哦 我有很多很多的内容哦 我有很多很多的内容哦
我有很多很多的内容哦 我有很多很多的内容哦 我有很多很多的内容哦
</div>
<script>
/*三大家族
1. offset家族 : 获取元素 ‘自身’ 的真实宽高 和 真实位置
offsetWidth / offsetHeight : 获取 width+padding+border
offsetLeft / offsetTop : 获取 左/上 外边框 到定位父元素 左/上 内边框距离
2. scroll家族 : 获取元素 ‘内容’ 的真实宽高 和 位置
scrollWidth / scrollHeight : 获取内容的宽高
scrollLeft / scrollTop : 内容的位置(就是滚动条滚动的距离)
3.client家族 : 获取元素 ‘可视区域’ 宽高 和 位置
clientWidth / clientHeight : 可视区域大小
clientLeft / clientTop : 可视区域位置(就是左边框 和 上边框 宽度)
*/
let box = document.querySelector('.box')
//三大家族是dom语法,不是css样式。
//错误写法: 元素.style.offsetWidth
//正确写法: 元素.offsetWidth
// 1. offset家族
console.log(box.offsetWidth, box.offsetHeight)// 190 190
console.log(box.offsetLeft, box.offsetTop)// 100 100
//2. scroll家族
console.log( box.scrollWidth , box.scrollHeight )//153 419
console.log( box.scrollLeft , box.scrollTop )//0 0 默认没有滚动
//3. client家族
console.log( box.clientWidth , box.clientHeight ) // 153 170
console.log( box.clientLeft , box.clientTop ) // 10 10
</script>
</body>
</html>
获取网页滚动距离
- 给页面注册滚动事件:window.onscroll
- 获取页面滚动距离:html标签的scrollLeft/Top
注意
- 给window注册事件,可以避免由于不同浏览器引擎不兼容问题(
所以只要是给页面注册事件,就找window,只要是拿数据,就找html) - 如果需要拿到网页滚动条的数据,需要从HTML拿到数据,可以设置变量拿到
str = document.documentElement
三大家族
offset家族只允许查看,不能更改盒子;scroll家族能够更改盒子 offsetWidth scrollWidth clientWidth 包含部分辨析
- offsetWidth:内容+内边距+边框 2. clientWidth:内
- scrollWidth:内容+内边距
offsetHeight scrollHeight clientHeight 辨析
- offsetHeight:内容+内边距+边框(可视区域)
- clientHeight:内容+内边距(可视区域)
- scrollHeight:内容+内边距(包含滚动条隐藏的部分)
第六板块
window对象 : 浏览器窗口
- 是js中的顶级对象。 所有的全局函数、全局属性都是window对象的成员(属性+方法)
- 只要是window对象的成员,在使用时可以省略window
- window对象有一些特殊的属性不能被覆盖。 例如top不能作为全局变量名
window对象
- window.onload事件 :dom树 + 外部资源 加载完成后执行
- window.onbeforeunload事件 :页面关闭之前执行(一般用于存储重要数据)
- window.onunload事件 :页面正在关闭
window对象两个方法
- 打开新窗口: window.open()
- url 可选参数,网址
- target 相当于a标签的target : _self:当前页面 _blank(默认):新窗口
- feature 窗口尺寸、位置等属性
- replace 是否替换当前历史记录 一般不写,自动默认值
- 关闭新窗口: window.close()
location对象
- 使用最多的属性(网页跳转): location.href
- location对象三个方法 :
- location.assign() : 跳转网页。 作用与location.href一致
- location.replace() : 替换网页。 使用较少,因为替换后不能返回
- location.reload() : 刷新网页。 一般用于移动端
注意:
- a标签href:用于无条件渲染,没有逻辑性,点我跳转。例如:订单、商品详情
- 用于具有逻辑性跳转,例如登录(只有成功才会跳转)
history对象
history : 历史记录
history三个方法:
- history.back() : 返回上一页 等价于 history.go(-1)
- history.forward() : 前进下一页 等价于 history.go(1)
- history.go( 数字 ) : 到历史记录的具体哪一页
正数: 前进 1:前进1页 2:前进2页
负数: 回退 -1:回退1页 -2:回退2页
补充对象
navigator 浏览器信息对象
作用:收集用户信息
screen对象 :获取用户电脑分辨率
localStorage 存储对象
- localStorage语法 :
-
存数据: localStorage.setItem('属性名',属性值)
-
取数据: localStorage.getItem('属性名')
-
删数据: localStorage.removeItem('属性名')
-
清空数据: localStorage.clear()
注意
-
永久存储 : 除非手动清除,否则一直存在
-
只能存储字符串类型,如果存储其他类型,编译器会自动toString()转成字符串来存储
-
经典应用: 免登录
localStorage 浏览器可视化界面位置
localStorage和sessionStorage 比较
- localStorage和sessionStorage的区别?
-
相同点: 作用相同,都是存储数据
-
不同点:存储方式不同
localStorage : 硬盘存储(永久存储)
- 应用场景: 免登录
sessionStorage : 内存存储 (临时存储)
- 应用场景: 页面间传值
- localStorage和sessionStorage在用的时候有什么注意点吗?
- 只能存储字符串类型数据, 如果存储其他类型则编译器自动调用toString()转成字符串
- 如何解决storage存储对象只能存储字符串问题? (如何存储引用类型)
- 使用json格式存储
第七板块
正则表达式
两种书写语法:创建对象或者直接用双斜杠
//(1)创建一个正则对象 : 检测字符串中有没有a
let reg = new RegExp('a')
//(2)调用正则对象的test()方法
console.log( reg.test('123456') )//false
console.log( reg.test('abc456') )//true
或者
console.log( /a/.test('ikun') )//false
console.log( /a/.test('akun') )//true
原义文本字符 : 字符串本身的含义。
举例: /abc/ , 检测字符串有没有abc. 既不是有a 或 有b 或 有c,也不是有a 且 有b 且 有c,就是看有没有字符串叫做abc.(想的越简单越正确,越复杂越错误)
元字符 : 改变自身含义的字符 (类似于js中的关键字)
. \ | () [] {} $ ^ * + ?
正则:^ 符号
// /[^abc]/ : 检测有没有 不是 a b c任何一个的字符 (只要有不是a b c的任意字符)
console.log( /[^abc]/.test('a123'))//true
console.log( /[^abc]/.test('a1b2c3'))//true
console.log( /[^abc]/.test('abc123'))//true
console.log( /[^abc]/.test('abcaaabbbccc'))//false
预定义类
常见js转义符
开头和结尾的限制
-
开头边界:/^abc/
正确含义: 开头a + bc
错误含义: 以abc开头
(
注意:两句话对于正则表达式的工作原理理解不一样) -
结尾边界:/abc$/
正确含义:ab + c结尾
错误含义: 以abc结尾
-
严格匹配: 开头边界 + 结尾边界 同时使用/^abc$/
正确含义: 以a开头 + b + c结尾
错误含义: 以abc开头,以abc结尾
总结: 不是说开头有abc,结尾有abc。 而是指这个abc既要在开头,也要在结尾。唯一答案:abc本身
量词
// + 和 * 区别
// + 匹配要求 >=1 一定要先从数字位置开始找
console.log( 'a123456789abc'.replace(/\d+/,'X') )//aXabc
// * 可以匹配0次, a的位置有0次数字,把没有数字的位置替换成X (找到0次了,下班了)
console.log( 'a123456789abc'.replace(/\d*/,'X') )//Xa123456789abc
修饰符
//替换所有的a和A : 修饰符可以连写
// /a/ig : 全局匹配 且 不区分大小写
console.log( 'A123aaa456AAA'.replace(/a/ig,'X') )//X123XXX456XXX