《Javascript核心DOM、BOM操作》笔记
Javascript核心DOM、BOM操作(pink老师),笔记
-
DOM学习目标:能获得页面元素、给元素注册事件、操作元素的属性、创建元素、操作DOM节点。
-
console.dir(input等元素对象),打印对象所有方法和属性。
-
事件三要素:事件源、事件类型、事件处理程序
-
事件执行步骤;
1.获取事件源 (如:下拉控件)
2.注册事件(绑定事件) (如:鼠标移到上事件)
3.添加事件处理程序(采取函数赋值形式) (如:显示下拉内容)
- 通过
event
对象获得事件源信息
//button的click绑定的查询方法
function seachData() {
let btnText=$(event.target).text();//获得事件源文本
}
- Document 对象属性和方法
document.getElementsByClassName('') 返回文档中所有指定class的元素集合,作为 NodeList 对象。
document.getElementById('') 返回对拥有指定 id 的第一个对象的引用。
document.getElementsByName('name') 返回带有指定名称的对象集合。
document.getElementsByTagName('div') 返回带有指定标签名的对象集合。
document.querySelector('#demo/.classDiv/div') 返回第一个div控件
document.querySelectorAll(同上) 返回所有符合选择器的元素(数组)
document.body 返回html文档的body元素
document.documentElement 返回html文档的html根节点
-
vue通过ref为控件设置属性:
this.$refs['refName'].$el.querySelectorAll('input')[0].style.cursor = 'not-allowed';//不允许操作
-
给按钮注册事件
document.getElementById('btnStart').onclick=function(){
document.getElementById('txt1').value++;//数字不断加1
};
- html中disabled和readonly区别:
- disabled属性作用于所有表单元素。
- readonly属性只对
<input type="text/number/password">、<textarea>
等可以输入的表单元素有效。- disabled属性元素值表单无法被提交。readonly不受影响。
- 修改元素样式、元素属性值设置、移除与获得
document.getElementById('txt1').style.color='red';//该input文本颜色(行内样式,一次只能一个样式)
document.getElementById('txt1').className='样式类名1 类名2';//为input修改class属性(可一次性为控件添加大量样式)
list[i].removeAttribute("readOnly");//【移除属性】
list[i].setAttribute("readOnly", true);//【为属性赋值(支持自定义属性)】
document.querySelector('div').id;//【获得属性方法1(只能获得本身自带)】
document.querySelector('div').getAttribute('id');//【获得属性方法2(获得自带+自定义属性)】
- 自定义属性,目的是保存一些数据,方便在页面者使用。只能用getAttribute方法获得内容。
- H5规定,自定义属性都是
data-
开头并赋值。<div id='a' data-index='1' data-list-name='abc'>内容</div> var div=document.querySelector('#a'); console.log(div.dataset)//【返回div 所有`data-`开头的自定义属性。】 console.log(div.dataset.index)//【返回div data-index的自定义属性值。】 console.log(div.dataset.listName)//【属性是驼峰命名法,返回div data-list-name的自定义属性值。】
网页节点增删改查
- DOM操作核心:对元素、属性进行创建和增删改查、事件操作。
- 节点选取:通过DOM方法(get...ById/ByTagName等);通过节点“父子兄”关系获得(逻辑性强,但是兼容差)。
- 节点,至少要有“nodeType类型、nodeName名称、nodeValue值”。
- html中元素对象有3类:文本节点值是3(如:文字、空格、换行);属性节点是2(如href等),元素节点是1(如input、div等).
var div1=document.querySelector('#a');
div1.parentNode;//离元素最近的父亲节点(就近原则),找不到就null
div1.childNodes;//所有的各类子节点(返回集合)
div1.children;//所有的元素类子节点
div1.first/lastElemnetChildren;//首尾元素类子节点
div1.nextElementSibling;//下一个兄弟节点(支持那3类)
div1.previousElementSibling;//上一个。。
div1.appendChild(document.createElement('li'));//指定节点后追加节点
div1.insertBefore(创建的节点对象,A);//A对象前面插入元素
div1.removeChild()//删除父内的子元素
var copyObj=div1.cloneNode();//复制节点(false仅copy标签,true则copy标签+内容)
-
练习:用上面知识点动态一个table并填入内容,最后一列是删除,有一个添加按钮可动态加到table下面。
-
三种动态创建元素:(innerHTML比createElement高效)
document.write('<div>123</div>');//写入页面内容流,但是文档流执行完毕,则它会导致页面全部重绘(write的内容覆盖旧的)
element.innerHTML;//技巧--放到数组最后join赋值则1000次循环只会几毫秒。如果循环内拼接字符串,会非常耗时(1000个耗时3s)。结构复杂
document.createElement();//(循环创建1000个耗时20ms),结构清晰
事件
- 目录:
出元素注册事件的两种方式
删除事件的两种方式
DOM事件流的三个阶段
利用事件对象完成跟随鼠标案例
阻止冒泡的兼容性函数
事件委托的原理
常用的鼠标和键盘事件
- 传统注册方式:(注册事件唯一性 —— 同一个元素同一个事件只能一个设置一个函数,后注册覆盖前面的)
<button onclick='alert(1)'/>
或
btn.onclick=function(){}
- 方法监听注册方式:w3c推荐
eventTarget.addEventListener(事件类型字符串,函数,bool可选参数)
(仅IE9+)。同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行。
- 在目标对象上指定监听器,当该事件触发时执行处理函数。
- 事件类型串:click、mouseover等不带on。
- 注册事件有两种方式:传统方式和方法监听注册方式。
- 监听方式注册事件
var btns = document.querySelectorAl1( ' button');
btns[1].addEventListener('click',function(){
alert('1');
});//监听方式加事件1
btns[1].addEventListener('click',ff);//监听方式加事件2
function ff(){ alert(22);}
btns[1].removeEventListener('click',ff)//删除事件(要移除的事件必须指明方法名称)
-
删除事件方式:传统方式注册事件的删除——
控件对象.onclick=null;
-
DOM事件流
- 事件流描述的是从页面中接收事件的顺序。
- 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
- 事件流:当为div加click事件,实际是按
document -> html -> body -> div
依次触发click事件,叫“捕获阶段”,逆过程叫“冒泡阶段”。像极了往水里丢石头,先下沉到底后冒泡。addEventListener(type, listener[,usecapture])
第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(默认值),表示在事件冒泡阶段调用事件处理程序。
- 验证捕获阶段传递顺序办法:分别为body和div注册click事件,设为true,点击后依次按父子顺序弹提醒。
- 无冒泡的事件
onblur、onfocus、onmouseenter、onmouseleave
事件对象
- 事件对象只有发生了事件才会存在,系统给我们创建,不需要我们传递参数。
- 事件对象是一系列跟事件相关的数据集合,比如鼠标坐标或可以判断用户按下了哪个键。
- 常见事件对象属性:
event.target 触发事件的对象。this返回的是绑定事件的对象(如给ul绑定click事件,点了li元素`console.log(this)`返回ul对象)。 event.currentTarget 类似this返回值(低浏览器不兼容)。 event.type 返回事件的类型比如click、mouseover不带on event.preventDefault() 该方法阻止默认事件(默认行为),比如不让链接跳转 event.stopPropagation() 阻止冒泡标准
- 引子:给每个li加click事件。
- 事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响每个子节点。
- 案例:给ul注册点击事件,然后利用事件对象的target 找到点击的li,因为事件会冒泡到ul上,就会触发事件监听器。
- 事件委托作用:我们只操作了一次DOM,提高了程序的性能。
document.querySelector('ul').addEventListener('click',function(e){ e.target.style.backgroundColor='gray';//点击的li置灰 })
contextmenu
主要控制是否显示上下文菜单,selectstart
阻止选中文字
document.addEventListener('contextmenu', function(e){//
e.preventDefault() ;
})
- MouseEvent对象
e.clientX/Y 获得鼠标点击时距离浏览器边缘x/y坐标(忽略滚动条)
e.pageX 鼠标相对浏览器内衬x坐标(考虑滚动条)
e.pageY 。。。
e.screenX/Y 获得鼠标点击时距离屏幕边缘x/y坐标
element.getBoundingClientRect()
用于获得页面中某个元素的左右上下值(类似上面screenX/Y和clientX/Y)分别相对浏览器视窗的位置(不包含文档卷起的部分)。- 键盘事件
- onkeydown和keypress都是鼠标按下事件,但是后者对shift、箭头键等不能识别。
- 3个事件有顺序
keydown → keypress → keyup
。keyup和keydown不分字母大小写。keypress区分大小写。只有keyup时文字才进入文本框。- 键盘事件对象,keyCode返回按键ASCII值(可以通过如下代码在chrome贴到控制台回车后,在页面里按按键即可查看)
document.addEventListener('keydown', function(e){ console.log(e.keyCode ); })
BOM
- BOM(浏览器对象模型),提供了与浏览器窗口进行交互的东西,核心对象是window。BOM缺乏标准。js标准是ECMA制定,DOM是W3C制定,而BOM最初是Netscape浏览器标准一部分。
- DOM顶级对象的document。BOM则是window。BOM包含了DOM。
window
=document+location+navigation+screen+history
- window对象是浏览器的顶级对象,它具有双重角色。
- 1.它是JS访问浏览器窗口的一个接口。
- 2.它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。
console.dir(window);
——可以查看window对象都有什么。- js写在html尾部。写在顶部则可借用
window.onload
(页面全部(dom元素、图片、flash、css等)加载完)一个页面只能有一个,添加侦听事件可以多个。IE9+有DOMContentLoaded仅DOM加载完就触发,不含样式表,图片,flash等。比load事件先执行。 window.onresize
页面大小调整时触发。window.innerWith
浏览器窗口大小- 两种定时器函数并说出区别
var aa = window.setTimeout(函数,延迟毫秒数);
定时器,到时候执行函数(也叫执行回调函数)。时间可省略,没有则默认0即立刻执行。window.clearTimeout(定时器别名)
清除定时器。window.setInterval(函数,间隔毫秒数)
,每间隔这个时间,就调用一次回调函数。window.clearInerval(定时器别名)
清除定时器。- 为什么要用 setTimeout 模拟 setInterval?定时器指定的时间间隔,表示的是何时将代码加到消息队列,而不是何时执行代码。所以真正何时执行代码的时间是不能保证的,取决于何时被主线程的事件循环取到,并执行。setInterval 缺点是很明显的,为了解决这些弊端,可以使用 setTimeout() 代替。在前一个定时器执行完前,不会向队列插入新的定时器(解决缺点一),保证定时器间隔(解决缺点二)
- 一般情况下
this
最终指向的是那个调用它的对象。
- 全局作用域或普通函数中this指向全局对象window。
console.log(this)
可通过这样查看this是什么。
- JS执行机制
- js是单线程的。所有任务都要排队。
- h5提出web worker标准,允许js脚本创建多个线程,于是js出现了同步和异步。
- js把同步任务放到主线程执行栈,异步任务(回调函数:定时器,普通事件,资源加载)放到任务队列(消息队列)中执行。
- 先执行完同步任务,最后把异步任务放到主线程去执行。
console.log(1); setTimeout(function() { console.log(3); },0); document.onclick=fun; console.log(2); //最终打印:1,2,3。只有点击后才会把fun放入异步任务中,然后放入主线程中执行。
- 由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)
location
对象完成页面之间的跳转(可F12输入location
回车查看)
location.href 获取或者设置整个URL
location.search 返回参数
location.host 返回主机(域名)www.itheima.com
location.port 返回端口号,如果未写返回空字符串
location.pathname 返回路径
location.hash 返回片段 #后面内容常见于链接锚点
location.assign() 跟href一样,可以跳转页面(也称为重定向页面,可后退)
location.replace() 替换当前页面,因为不记录历史,所以不能后退页面。
location.reload() 重新加载页面,相当于刷新按钮或者f5,如果参数为true,强制刷新(ctrl+f5)。
- navigator对象包含浏览器信息,最常用的是userAgent(客户端发送到服务器的user-agent头部信息,判断是手机还是pc浏览器)
history提供的方法实现页面刷新
//JS通过UA(userAgent)判断加载手端或pc端页面
if(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
window.location.href='http://m.ke361.com';//手机
}else {
window.location.href = "http://www.ke361.com";//电脑
}
- history对象
back() 可以后退功能
forward() 前进功能
go(参数) 前进后退功能。参数如果是1前进1个页面,如果是-1后退1个页面
- 存储容量:sessionStorage约5MB(同一个页面)、localStorage约20MB(同一域名所有页面)。
- offset(元素偏移量)和style区别:
- offset可以得到任意样式表中的样式值
- offset系列获得的数值是没有单位的
- offsetWidth包含padding+ border+width
- offsetWidth等属性是只读属性
- 所以,我们想要获取元素大小位置,用offset更合适
- style只能得到行内样式表中的样式值
- style.width获得的是带有单位的字符串
- style.width获得不包含padding和border的值
- style.width是可读写属性
- 所以,我们想要给元素更改值,则需要用style改变
- 元素可视区client系列:使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态的得到该元素的边框大小、元素大小等。返回数值不含边框含padding和内容区的宽和高,其他都与offset一样。
- 立即执行函数:不需要调用,立马能够自己执行的函数。主要作用:创建一个独立的作用域。避免了命名冲突问题。
写法:
(function(){})()
或(function(){}())
。内部变量都是局部变量。
- 移动端项目,考虑到兼容性,现在使用比较多的是用rem。
flexible.js
是淘宝为了适配移动端开发的一个插件。 - rem(font size of the root element)是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。
- onpageshow 事件在用户浏览网页时触发。onpageshow 事件类似于 onload 事件,onload 事件在页面第一次加载时触发, onpageshow 事件在每次加载页面时触发,即 onload 事件在页面从浏览器缓存中读取时不触发。
- 元素滚动scroll系列:
element.scrollTop 返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft 返习被卷去的左侧距离,返回数值不带单位
element.scrollWidth 返回自身实际的宽度,不含边框,返回数值不带单位
element.scrollHeight 返回自身实际的高度,不含边框,返回数值不带单位
-
三大系列对比
element.offsetWidth 返回自身包括padding、【边框】、内容区的宽度,返回数值不带单位
element.clientWidth 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
element.scrollWidth 返回自身实际的宽度,不含边框,返回数值不带单位。
offset系列经常用于获得元素位置offsetLeft offsetTop
client经常用于获取元素大小clientwidth clientHeight
scroll经常用于获取滚动距离scrollTop scrollLeft
注意页面滚动的距离通过window.pagexoffset获得。
- 获得div标签坐标和宽高信息
let h = divObj.offsetHeight;//div高度
let w = divObj.offsetWidth; //div宽度
let y = divObj.offsetTop; //div左上点的y坐标
let x = divObj.offsetLeft; //div左上点的x坐标
- js获得电脑屏幕分辨率的宽*高:
window.screen.width, window.screen.height
- mouseover鼠标经过自身盒子和子盒子都会触发(有冒泡)。mouseenter只会经过自身盒子触发(无冒泡)。
- 动画核心原理:通过定时器setInterval()不断移动盒子位置。
- 缓动动画就是让元素运动速度有所变化,最常见的是慢慢停下来。
- 缓动动画核心算法:
(目标值 - 现在的位置) / 10
做为每次移动的距离步长。//封装动画函数(参数:元素对象,目标位置,回调函数) function animate(obj, target,fun) { clearInerval(obj.timer);//先清除以前的定时器,只保留当前的一个定时器执行 obj.timer = setInterval(function() { var step=(target-obj.offsetLeft)/10;//缓动动画步长 step>0?Math.Ceil(step):Math.floor(step);//(不出现小数) if (obj.offsetLeft >= target) { clearInterval(obj.timer);//停止动画本质是停止定时器 if(fun){fun();}//执行回调函数 或高级版:fun&&fun(); —— 短路运算 } obj.style.left = obj.offsetLeft + step + 'px'; },15); } var span = document.queryselector('span'); var btn = document.queryselector('button'); btn.addEventListener('click', function() { animate(span,500, function(){alert('你好')} );//调用函数 })
- 点击左右滚动显示图片,在点击过快时图片无法显示完就到下一张了。解决办法—— 节流阀:
if(flag){flag = false; do something ;flag =true;}
关闭和打开水龙头。结合上面动画函数,则flag=true放到回调函数中最合适,这样在一张图片结束后才执行下一个次动画。 - 滚动窗口至文档中的特定位置
window.scroll(x, window.pageYOffset)
- 移动端特有的touch事件
touchstart 手指触摸DOM事件
touchmove 手指移动事件
touchend 手指离开事件
- 上述三个事件对象常见属性
touches 正在触摸屏幕的所有手指的一个列表
targetTouches (最常用)正在触摸当前DOM元素上的手指的一个列表
changedTouches 手指状态发生了改变的列表,从无到有,从有到无变化
- 移动端拖动的原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置+手指移动的距离
- 手指移动的距离:手指滑动中的位置减去 手指刚开始触摸的位置
- 拖动元素三步曲:
- (1)触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置
- (2)移动手指touchmove : 计算手指的滑动距离,并且移动盒子
- (3)离开手指touchend:
- 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动e.preventDefaultO;
- H5新属性:
classList
返回元素的类名集合。也可以添加或移除及切换css类。
var div = document.querySelector('div');
console.log(div.classList);//classList返回元素的类名
div.classList.add('不带点的类名');//追加类名
div.classList.remove('不带点的类名');//移除指定类名
div.classList.toggle('不带点的类名');//切换类名(有则移除,没有则追加上)
- 移动端click事件会议300ms的延迟,原因是移动端屏幕双击缩放页面,300ms内点了两下就会缩放。
- 解决方案
- 1.禁用浏览器默认的双击缩放行为且去掉300ms点击延迟 ——
<meta name="viewport" content="user-scalable=no">
- 2.利用touch事件自己封装事件解决300ms延迟。原理就是:1.当手指触摸屏幕,记录触摸时间。2.当手指离开屏幕,用离开的时间减去触摸时间,小于150ms且没滑动屏幕就视为点击。
fastclick
插件。插件就是js文件,为解决一个专门问题而封装的功能单一的方法。
- Swiper是纯javascript打造的滑动特效插件,面向手机、平板电脑等移动终端。
- 常用的“焦点图/幻灯片”“Tab标签切换”“图片滚动”“无缝滚动”等只需要一个SuperSlide即可解决!
- iScroll是一个高性能,资源占用少,无依赖,多平台的javascript滚动插件。
- 移动端视频插件
zy.media.js
,实现所有浏览器播放器风格统一。
<video src='a.mp4' controls></video>
- 框架,顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。前端常用框架
Vue、Angular、React
等。 - 框架和插件区别:
框架:大而全,一整套解决方案
插件:小而专一,某个功能的解决方案