8WebAPI
- Web API和JS基础关联性
- JS的组成
- ECMAScript:JavaScript语法【JavaScript基础】
- DOM:页面文档对象模型
- BOM:浏览器对象模型
- DOM和BOM为Web APIS阶段
- JS基础阶段
- 我们学习的是ECMAScript标准规定的基本语法
- 要求同学们掌握JS基础语法
- 只学习基本语法,做不了常用的网页交互效果
- 目的是为了JS后面的课程打基础、做铺垫
- Web APIs阶段
- Web APIs是W3C组织的标准
- Web APIs我们主要学习DOM和BOM
- Web APIs是我们JS独有的部分
- 我们主要学习页面交互功能
- 需要使用JS基础的课程内容做基础
- 总结:
- JS基础学习ECMAScript基础语法为后面做铺垫,Web APIs是JS的应用,大量使用JS基础语法做交互效果
- JS的组成
- API和Web API
- API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
- 简单理解:API是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。
- Web API
- Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
- 现阶段我们主要针对于浏览器讲解常用的API,主要针对浏览器做交互效果
- MDN详细API:https://developer.mozilla.org/zh-CN/docs/Web/API
- 因为Web API很多,所以我们将这个阶段称为Web APIs
- 总结:
- API是为我们程序员提供的一个接口,帮助我们实现某种功能,我们会使用就可以了,不必纠结内部如何实现
- Web API主要针对浏览器提供的接口,主要针对于浏览器做交互效果。
- Web API一般都有输入和输出(函数的传参和返回值),Web API很多都是方法(函数)
- 学习Web API可以结合前面学习内置对象的方法的思路学习
- 这个API是干什么的
- 它里面需不需要参数
- 它的返回值是什么
- API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
- DOM
- DOM简介:
- 什么是DOM:
- 文档对象模型(Document Objext Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
- W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
- 什么是DOM:
- DOM简介:
- DOM树
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:页面中的所有标签都是元素,DOM中使用element表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
- DOM把以上内容都看作是对象
- 获取元素
- 如何获取页面元素
- DOM在我们实际开发中主要用来操作元素。
- 我们如何获取页面中的元素呢
- 获取页面中的元素可以使用以下几种方式:
- 根据ID获取
- 根据标签名获取
- 通过HTML5新增的方法获取
- 特殊元素获取
- 根据ID获取
- 使用getElementById()方法【只有document对象才有这个方法】可以获取带有ID的元素对象。
- 语法格式:
- <div id="目标id名">内容</div>
- <script>
- 如何获取页面元素
var 变量名=document.getElementById("目标id名")
</script>
- 目标id名是大小写敏感的字符串,代表了所要查找的元素的唯一ID
document.getElementById("目标id名")中的id唯一,所以getElementById中的Element为单数。
- Element是一个Element对象,如果当前文档中拥有特定ID的元素不存在则返回null
- 返回值:返回一个匹配到ID的DOM Element对象。若在当前Document下没有找到,则返回null。(返回的是一个元素对象)
- 注意:因为我们文档页面从上往下加载,所以先得有标签 所以script写到标签的下面
- 根据标签名获取
- 使用getElementsByTagName()方法可以返回带有指定标签名的对象的集合。
- 语法格式:
- 格式1:获取整个文档中的目标标签
<script>
var 变量名=document.getElementsByTagName('目标标签名')
</script>
- 返回的是 获取过来元素对象的集合 以伪数组的形式存储的
所以document.getElementsByTagName('目标标签名')中的Elements为复数
会将整个文档中的目标标签获取过来
- 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
- 得到元素对象是动态的
- 格式2:获取整个文档中的某个元素下面的目标标签
- Element.getElementsByTagName
Element的获取方式:
document.getElementById('目标元素名')
document.getElementsByTagName('目标元素名')[索引号]
document.getElementsByClassName('目标元素名')[索引]
因为element为单数,所以是单个元素对象,
<script>
var 对象名=document.getElementById('目标元素名')
var 对象名2=对象名.getElementsByTagName('目标标签名')
</script>
- var 对象名=document.getElementById('目标元素名')先找到目标元素
- var 对象名2=对象名.getElementsByTagName('目标标签名')再在这个目标对象下面找到需要的目标标签对象
- 通过HTML5新增的方法获取
- 语法格式:
- 格式1:
- document.getElementsByClassName('类名'); /* 根据类名返回元素对象集合返回的是 获取过来元素对象的集合 以伪数组的形式存储的 */
- 格式2:
- document.querySelector('选择器');//根据指定选择器返回第一个元素对象
- 格式1:
- 语法格式:
选择器的书写方式(切记里面的选择器需要加符号)
.类名
#类名
标签名
- 格式3:
- document.querySelectorAll('选择器');/*根据指定选择器返回元素对象集合,获取过来元素对象的集合 以伪数组的形式存储的 */
- 格式3:
选择器的书写方式(切记里面的选择器需要加符号)
.类名
#类名
标签名
- console.dir(id名/对象名)
- 打印我们返回的元素对象 更好的查看里面的属性和方法
- 获取body元素(返回body元素对象)
- 语法格式:document.body;
- 获取html元素(返回html元素对象)
- 语法格式:document.documentElement;
- 查:
- 获取DOM节点:
- 内定的直接使用:
- document【文档节点】
- document.body【body元素节点】
- 元素节点没有nodeValue属性
- document.head【head元素节点】
- document.documentElement【html元素节点】
- document.title【文档标题】
- id名
- 通过方法获取节点:
- getElement系列【动态获取】:
- 通过id获取【只有document对象才有这个方法】【全线兼容:所有浏览器版本都支持】:
- getElement系列【动态获取】:
- 内定的直接使用:
- 获取DOM节点:
语法:document.getElementById(‘id名’)
Id名不要和name名相同,因为在ie低版本浏览器会将name属性名当作id名。
- 通过tagName标签名获取【获取的是伪数组或叫类数组】【全线兼容】
语法:document.getElementsByTagName(“标签名”)
- 通过类名获取【获取的是伪数组或叫类数组】【低版本浏览器不兼容】
语法:document.getElementsByClassName(‘类名’)
- 通过name获取【获取的是伪数组或叫类数组】【name不能和id重名】:
语法:document.getElementsByName(“name属性值”)
一般用在表单标签的name属性值,也可以用在其他标签上。
只有部分标签可用,通过name属性获取元素(表单,表单元素,img,iframe)
- getElementById(“id名”)和getElementsByName(“name属性值”)这两个方法只能通过document对象来调用
- getElement系列的其他方法的调用,对象只要是元素对象都可以调用。
- 动态获取:当DOM树结构某部分被删除后,页面上的元素也跟着树结构被删除的部分删除,控制台获取的伪数组元素对象集合里面的单个元素也被删除了。
删除语法:单个元素对象.remove()
该语法删除后,页面上的元素就会被删除,单个元素对象如果是在某个伪数组元素集合里面获取的,那么这个伪数组元素集合里面的该对象元素会动态删除。如果单个元素对象不是在伪数组元素集合里面获取的,那么只会删除页面上的元素,对控制台其他打印没有影响。
- query系列【静态获取】【挂载到元素对象上的】【ie7版本及以下不兼容】:
- querySelector【获取的是单个元素】:
- query系列【静态获取】【挂载到元素对象上的】【ie7版本及以下不兼容】:
语法:document.querySelector(“css选择器”)
获取第一个选择器选中的元素
- querySelectorAll【获取的是一个元素集合】:
语法:document.querySelectorAll(“css选择器”)
获取所有被选择器选中的元素
- 静态获取:当DOM树结构某部分被删除后,页面上的元素也跟着树结构被删除的部分删除,控制台获取的伪数组元素对象集合里面的单个元素对象却没有被删除
- 通过一个节点获取其他节点:
- 获取父节点:
- node.parentNode【获取父节点】
- node.parentElement【获取父元素节点】
- 获取子节点
- node.childNodes【获取所有子节点】
- node.children【获取所有子元素节点】
- 获取兄弟节点
- node.nextSibling【获取当前节点下一个兄弟节点】
- node.previousSiling【获取当前元素上一个兄弟节点】
- node.nextElementSiling【获取当前节点下一个兄弟元素节点】
- node.previousElementSibling【获取当前节点上一个兄弟元素节点】
- 获取父节点:
- 希望看这个节点的属性:
- console.dir(节点)
- 增:
- 创建DOM节点:
- 创建元素节点:
- 语法:document.creatElement(‘标签名’)
- 创建文本节点:
- 语法:document.creatTextNode(‘文本内容’)
- 创建注释节点:
- 语法:document.creatComment(‘注释内容’)
- 创建文档片段节点:
- 语法:document.creatDocumentFragment()
- 该语法创建了一个节点区域【也相当于一个节点】,可以在该节点中创建好其他节点后,直接将该节点放入DOM树中。
- 语法:document.creatDocumentFragment()
- 创建元素节点:
- 插入节点:
- parentNode.appendChild(创建的节点名)
- 在parentNode这个节点里面的最后一个子节点添加创建的节点
- 如果创建的节点名是通过DOM获取过来的元素节点,则是删除原来的节点位置,插入到parentNode节点内子节点的最后一个位置【剪切到最后一个子节点位置】
- parentNode.insertBefore(A,B)
- 返回值为A元素对象
- A节点如果是创建的节点:在parentNode这个节点里面的子节点B的前面添加A节点
- 如果A节点是以前DOM树上的节点获取过来的:删除原来的A节点,将删除的A节点插入到B元素节点的前面。【可以理解为剪切操作】
- parentNode.appendChild(创建的节点名)
- 创建DOM节点:
- 删:
- 删除节点树上的节点:
- 通过自己删除自己:
- 语法:node.remove()
- 没有返回值
- 页面中的自己这个元素会消失
- 语法:node.remove()
- 通过父节点删除自己:
- 语法:parentNode.removeChild(child)
- parentNode:父节点的节点名
- child:子节点节点名,即自己这个元素节点
- 返回值为被删除的自己这个元素
- 页面中的自己这个元素会消失
- 语法:parentNode.removeChild(child)
- 通过自己删除自己:
- 删除节点树上的节点:
- 改:
- 替换:
- parentNode.replaceChild(A,B)
- A节点为创建的节点:用节点A替换节点B
- A节点为原节点树上获取的节点:删除原来的A节点,然后将删除的A节点将B节点替换掉
- 返回值为A这个元素对象
- parentNode.replaceChild(A,B)
- 替换:
- 判断一个元素节点有没有子节点方法:
- element.hasChildNodes()
- element:父元素元素对象节点
- 如果有子节点【包括内部的文本节点,和注释节点】返回true
- 如果没有返回false
- 应用场景:
- 删除文本节点
- 删除空标签节点
- element.hasChildNodes()
- 元素节点常用的属性:
- innerHTML获取元素节点的内容,可读可写
- 如果内容中有符合html格式的标签,标签在会被解析,即可以在控制台上看见对应的标签。
- 在页面上标签会被解析,能看见标签的表达效果
- innerText获取元素节点的内容,可读可写
- 如果内容中有符合html格式的标签,标签不会被解析,即控制台上看不见对应的标签,标签会被剔除。
- 在页面上标签不会被解析,会连同标签在页面上显示
- 注意:老版本的火狐不兼容innerText火狐有自己的textContent但时textContent老版本IE(8及以下)不兼容
- innerHTML获取元素节点的内容,可读可写
- 元素节点常用的方法:
- 设置或获取标签属性:
- element.setAttribute(“class”,”on”)
- element:元素对象节点
- class:元素对象标签属性名
- on:设置的element元素对象中class属性的标签属性值
- 效果:将class属性的属性值设置为on
- element.getAttribute(“class”)
- element:元素对象节点
- class:获取的元素对象标签属性名
- 返回值:该element元素对象标签 属性名为class的属性值
- element.removeAttribute(“class”)
- element:元素对象节点
- class:移除的元素对象标签属性名
- 效果:页面中element会去掉class属性和和其对应的属性值
- 返回值:没有返回值
- 获取元素对象节点的class属性值【类名】【得到的是一个字符串】:
- element.className 【可读可写】
- 点操作可以获取和设置标签合法属性:
- 得到的是合法属性值
- 如果操作的是自定义属性【不合法的】,那么元素对象标签不会有任何反应【setAttribute可以操作不合法的属性】
- H5新增的元素节点的classList属性
- 语法:element.classList
- 返回值:所有类名的伪数组
- classList属性是一个类数组,它里面存放了element元素的所有类名,其身上有几个常用的方法:
- add(value):将给定的参数value字符串添加到元素class属性中,如果存在就不添加了
- remove(value):将给定的参数字符串从class属性中删除
- toggle(value):检测class属性中是否有参数字符串,有则删除,返回false。没有则添加,返回true
- contains(value):检测class属性中是否有value字符串,有则返回true,没有就返回false
- 语法:element.classList
- H5新增的操作data- 开头的自定义属性:
- 获取该自定义属性的属性值:
- 方式一:element.getAttribute(‘class’)
- 方式二:element.dataset.自定义属性名
- 设置自定义属性的属性值:
- element.dataset.自定义属性名=属性值
- 获取该自定义属性的属性值:
- element.attributes[索引号]
- 获取元素对象的属性【键值对】
- element.attributes[索引号].name:获取该属性的属性名【只读】
- element.attributes[索引号].value:获取该属性的属性值【可读可写】
- 获取元素对象的属性【键值对】
- element.setAttribute(“class”,”on”)
- 设置或获取标签属性:
- JavaScript脚本化的CSS:
- 本质能在js中操作CSS样式
- 点语法只能获取行内样式【可读可写】:
- 例子:box.style.width
- 主流浏览器获取计算样式表的方法【可读】:
- window.getComputedStyle(element):
- element:元素对象
- 获取element元素对象的所有CSS样式。
- 当element后面还有一个参数时,参数为“after”或“before”,是获取的element元素里面的伪元素对象
- 获取单个样式:window.getComputedStyle(element).style
- window.getComputedStyle(element):
- 点语法只能获取行内样式【可读可写】:
- 本质能在js中操作CSS样式
element:元素对象
style:单个样式【可以是width,heigth等css里面的连字符采用小驼峰】
如果想用连字符,需要加中括号:
例子:getComputedStyle(box)[‘background-color’]
- IE8及以下浏览器,获取计算样式表的方法:
- element.currentStyle
- 处理兼容性:
- var styleObj = null
- IE8及以下浏览器,获取计算样式表的方法:
if(window.getComputedStyle){
//主流浏览器
styleObj=getComputedStyle(element)
}else {
//IE8以下
styleObj = element.currentStyle
}
- 设置元素样式:
- 只能通过行内样式设置:element.style.属性=属性值
- 设置元素样式:
- 自己手动计算一些元素的值,不太方便,因此W3C在提供DOM也提供了一些方便操作的属性,让我们获取一些常用的元素值
- element.offsetWidth:
- Width+左右padding+左右border
- element.offsetHeight:
- Height+上下padding+上下border
- element.offsetLeft:
- left+margin-left:相对于定位父级【有position样式的元素】左边框的距离
- 兼容性差
- IE9,IE9+,chrome等高级浏览器可用,在没有定位父级时,默认为body
- IE6,7,在没有定位父级时,offsetParent就是离自己最近的有width/height的父级元素
- IE8,无论自己是否定位,自己的offsetParent就是自己祖先元素中,离自己最近的已经定位的元素。
- element.offsetTop:
- top+margin-top:相对于定位父级【有position样式的元素】上边框的距离
- 兼容性差,IE9,IE9+,chrome等高级浏览器可用
- dom.clientLeft:
- border-left-width
- dom.clientTop:
- border-top-width
- element.clientWidth:
- width+左右padding
- element.clientHeight:
- height+上下padding
- element.offsetWidth:
- 获取元素的滚动值:
- 获取滚动元素的宽高:
- 当元素实际内容超过设置的内容时
- dom.scrollWidth🡺元素实际内容的width
- dom.scrollHeight🡺元素实际内容的height
- 当元素实际内容超过设置的内容时
- 获取元素的滚动距离(数字类型的值):
- dom.scrollLeft滚动的水平距离
- dom.scrollTop滚动的竖直距离
- dom.scrollHeight自身实际高度
- 获取滚动元素的宽高:
- 滚动距离的兼容写法:
- 获取滚动条的滚动距离IE8以上:
- Window.pageXOffset页面滚动的水平距离
- Window.pageYOffset页面滚动的竖直距离
- 获取滚动条的滚动距离IE8及以下:
- document.documentElement.scrollLeft
- document.documentElement.scrollTop
- document.body.scrollLeft
- document.body.scrollTop
- 获取滚动条的滚动距离IE8以上:
- 浏览器页面滚动:
- window.scrollTo(x,y):
- 当页面可以滚动时,让滚动条滚动到指定位置
- window.scrollBy(x,y):
- 当滚动条可以滚动时,让滚动条滚动指定距离
- window.scrollTo(x,y):
- 事件基础
- 事件概述
- JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。(简单理解:触发---响应机制)
- 网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。
- 事件是有三部分组成(我们也称为事件三要素):
- 事件源:事件被触发的对象(需要获取事件对象,事件对象是单个元素【DOM元素】,不能是元素集合)
- var 对象名=document.getElementsByClassName('类名')[索引号];//获取事件源
- 事件类型:如何触发(赋值方式)
- onclick:鼠标点击触发
- 事件源:事件被触发的对象(需要获取事件对象,事件对象是单个元素【DOM元素】,不能是元素集合)
- 事件概述
对象名.onclick = function(){
alert('点求i想')
}
- 事件处理程序:通过一个函数赋值的方式完成
- 执行事件的步骤
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
- 事件语法【0级事件:只能绑定一个事件处理函数】:DOM元素.‘on’+事件名 = 事件处理函数
- 常见的鼠标事件
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发(表单,输入框有了焦点触发) |
onblur | 失去鼠标焦点触发(表单) |
onmousemove | 鼠标移动触发【持续触发】 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
oncontextmenu | 点击鼠标右键触发(浏览器有默认的右键行为)不常用 |
ondbclick | 双击鼠标左键触发 |
onmouseenter | 鼠标进入元素时触发 |
onmouseleave | 鼠标离开元素时触发 |
- 滚轮事件:
- onmousewheel:鼠标滚轮在元素上滚动时触发(IE+chrome)
- mouse鼠标,wheel就是轮子
- 滚轮方向值:
- event参数最重要的就是wheelDelta属性,表示滚动的方向,这是浏览器的规定:
- 鼠标往上滚[往前推滚轮]:event.wheelDelta属性值为
- event参数最重要的就是wheelDelta属性,表示滚动的方向,这是浏览器的规定:
- onmousewheel:鼠标滚轮在元素上滚动时触发(IE+chrome)
Chrome其值为180
IE其值为120
- 鼠标往下滚[往后拉滚轮],event.wheelDelta属性值为
Chrome其值为-180
IE其值为-120
- DOMMouseScroll:鼠标滚轮在元素上滚动时触发(firefox)
- 该事件只能通过DOM2级绑定事件添加。
- 语法:
- element.addEventListener(‘DOMMouseScroll’,function(ev){})
- 滚轮方向值:
- event参数最重要的就是detail属性,表示滚动的方向,这是浏览器的规定:
- 鼠标往上滚[往前推滚轮]:event.detail属性值为-3
- 鼠标往下滚[往后拉滚轮],event.detail属性值为3
- event参数最重要的就是detail属性,表示滚动的方向,这是浏览器的规定:
- DOMMouseScroll:鼠标滚轮在元素上滚动时触发(firefox)
- 滚轮事件兼容性封装:
document.addEventListener('mousewheel', mousewheelhandler)
document.addEventListener('DOMMouseScroll', mousewheelhandler)
function mousewheelhandler(event) {
event = event || window.event; //解决IE6,7,8和高级浏览器的不兼容
if (event.wheelDelta) {
var direction = event.wheelDelta > 0 ? 1 : -1
} else if (event.detail) {
var direction = event.detail > 0 ? -1 : 1;
}
return direction
}
- 键盘事件【事件源可以为document或表单【如果事件源是其他元素,只有在内部的表单中输入 键盘事件才会触发】】:
- onkeydown:按住键盘上任意键触发【持续触发】
- onkeypress:按住键盘上部分键触发【持续触发,功能键不会触发该事件】
- onkeyup:键盘上按键抬起时触发
- 常用功能键:
- CtrKey:e.ctrlKey【其值为true表示用户按下了CTRL键】
- shiftKey:e.shiftKey【其值为true表示用户按下了shift键】
- altKey:e.altKey【其值为true表示用户按下了alt键】
- 常用功能键:
- 资源事件:
- onload:页面或则图片加载完成时触发
- 焦点事件:
- onfocus:得到焦点触发
- onblur:失去焦点触发
- 解绑事件:
- 通过判断拦截,事件执行一次后就不再执行了
- 案例:
- 通过判断拦截,事件执行一次后就不再执行了
var btn = document.getElementsByTagName('button')[0]
var isTrue = false;
btn.onclick = function () {
if (isTrue) {
return
}
isTrue = true
console.log('我第二次点击了')
}
- 注销事件【在事件处理函数的内部最后写下注销事件语法】:
- 语法:
- DOM元素.‘on’+事件名 = null
- 语法:
- 注销事件【在事件处理函数的内部最后写下注销事件语法】:
- 操作元素
- JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性
- 改变元素内容(改变元素内容赋值;读取元素内容)
- 语法格式:
- 格式1:element.innerText
- 读取从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉(不会解析html标签,不会识别html标签)
- 格式2:element.innerHTML
- 读取起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行(会解析html标签,也会识别html标签)
- 格式1:element.innerText
- 语法格式:
- 不添加事件直接操作元素就是操作DOM
- 常用元素的属性操作
- innerText、innerHTML改变元素内容
- src、href
- id、alt、title
- 修改属性值的语法:元素对象.属性=‘属性值‘
- 分时显示不同图片,显示不同问候语
- 思路:
- 根据系统不同时间来判断,所以需要用到日期内置对象
- 利用多分支语句来设置不同的图片
- 需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性
- 案例:
- 思路:
<button class="greetings">上午好,</button>
<div class="container">
<img src="images/morning.png" alt="">
</div>
<script>
var btns = document.getElementsByClassName('greetings');
var consainers=document.getElementsByClassName('container');
var imgs = consainers[0].getElementsByTagName('img');
var date = new Date();
var hour = date.getHours;
if (hour >= 0 && hour <= 5) {
btns[0].innerHTML = '凌晨了,该休息了'
imgs[0].src = 'images/dawn.jpg'
} else if (hour > 5 && hour < 9) {
btns[0].innerHTML = '早上好呀'
imgs[0].src = 'images/morning.jpg'
} else if (hour >= 9 && hour < 11) {
btns[0].innerHTML = '上午好呀'
imgs[0].src = 'images/morning.jpg'
} else if (hour >= 11 && hour < 13) {
btns[0].innerHTML = '中午好呀'
imgs[0].src = 'images/noon.jpg'
} else if (hour >= 13 && hour < 16) {
btns[0].innerHTML = '下午好呀'
imgs[0].src = 'images/afternoon.jpg'
} else if (hour >= 16 && hour < 19) {
btns[0].innerHTML = '傍晚好呀'
imgs[0].src = 'images/dawn.jpg'
} else {
btns[0].innerHTML = '晚上好呀'
imgs[0].src = 'images/night.jpg'
}
</script>
- 表单元素的属性操作
- 利用DOM可以操作如下表单元素的属性:
- type、value、checked、selected、disabled
- 表单里面 的文字内容是通过value来修改的
- 10121835
- 利用DOM可以操作如下表单元素的属性:
- 禁用元素事件操作:
- 法一:元素对象名.disabled = true;
- 法二:this.disabled = true;
- this指向事件函数的调用者
- 点击按钮 密码的显示隐藏案例
<input type="password" class="pwd" placeholder="输入密码">
<span class="btn"></span>
<script>
var ipts = document.getElementsByClassName('pwd');
var btns = document.getElementsByClassName('btn');
var mark = true;
btns[0].onclick = function () {
if (mark == true) {
ipts[0].type = '';
mark = !mark;
btns[0].innerHTML = ''
} else {
ipts[0].type = 'password';
mark = !mark;
btns[0].innerHTML = ''
}
}
</script>
- 样式属性操作
- 我们可以通过JS修改元素的大小、颜色、位置等样式
- element.style.样式属性 行内样式操作(样式属性采用小驼峰命名法)
- element.className 类名样式操作
- 注意:
- JS里面的样式采取驼峰命名法 比如fontSize、backgroundColor
- JS修改style样式操作,产生的是行内样式,CSS权重比较高
- 我们可以通过JS修改元素的大小、颜色、位置等样式
- 关闭广告案例:
<div class="box">
<img src="images/wx.png" alt="" class="ig">
<div class="btn">X</div>
<div class="text">加我微信</div>
</div>
<script>
var btns = document.getElementsByClassName('btn');
var imgs = document.getElementsByClassName('ig');
var boxs = document.getElementsByClassName('box');
btns[0].onclick = function () {
boxs[0].style.display = 'none'
}
</script>
- 循环精灵图背景
- 可以利用for循环设置一组元素的精灵图背景
- 案例分析:
- 首先精灵图图片排列必须是有规律的(竖着一列排,且大小相同,距离相同)
- 核心思路:利用for循环 修改精灵图片的背景位置background-position
- 剩下的考验你的数学功底了
- 代码案例实现:
<div class="containner">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
var index = i * 44;
lis[i].style.backgroundPosition='0 -' + index + 'px'
}
</script>
- 显示隐藏文本框内容
- 当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。
- 案例分析:
- 首先表单需要2个新事件,获得焦点onfocus 失去焦点onblur
- 如果获得焦点,判断表单里面内容是否为默认文字,如果是默认文字,就清空表单内容
- 如果失去焦点,判断表单内容是否为空,如果为空,则表单内容修改为默认文字
- 代码案例:
<input type="text" value="输入吧">
<script>
var ipts = document.getElementsByTagName('input');
console.log(ipts)
ipts[0].onfocus = function () {
if (ipts[0].value === '输入吧') {
ipts[0].value = '';
}
this.style.color = 'skyblue'
}
ipts[0].onblur = function () {
if (ipts[0].value === '') {
ipts[0].value = '输入吧'
}
ipts[0].style.color = '#ccc'
}
</script>
- 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
- element.className = ‘类名’
- 使用element.style.样式属性=‘样式属性值‘
- 样式属性采取小驼峰命名法
- 注意:
- 如果样式修改较多,可用采取操作类名方式更改元素样式。
- class因为是个保留字,因此使用className来操作元素类名属性
- className会直接更改元素的类名,会覆盖原先的类名(如果原先的类的样式不想变,可用用多类名)
- 密码框格式提示错误信息
- 用户如果离开密码框,里面输入个数不是6~16,则提示错误信息,否则提示输入正确信息。
- 案例分析:
- 首先判断的时间是表单失去焦点onblur
- 如果输入正确则提示正确的信息颜色为绿色小图标变化
- 如果输入不是6到16位,则提示错误信息,颜色为红色小图标变化
- this.value.length
- 因为里面变化样式较多,我们采取className修改样式。
- 代码案例实现:
<div class="register">
<input type="password" name="" class="ipt" id="">
<p class="message">请输入6~16位密码</p>
</div>
<script>
var pwds = document.getElementsByClassName('ipt')
var messages = document.getElementsByClassName('message');
pwds[0].onblur = function () {
console.log(this.value.length)
if (this.value.length >= 6 && this.value.length <= 16) {
messages[0].innerHTML = '通过';
messages[0].style.color = 'green'
} else {
messages[0].innerHTML = '信息有误,请重新输入';
messages[0].style.color = 'red'
}
}
</script>
- 操作元素总结:
- 操作元素:
- 操作元素内容
- innerText
- innerHTML
- 操作常见元素属性
- src、href、title、alt等
- 操作表单元素属性
- type、value、disabled等
- 操作元素样式属性
- Element.style.‘样式属性‘=’样式属性‘
- Element.className=’类名’
- 操作元素内容
- 操作元素:
- 排他思想
- 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
- 所有元素全部清除样式(干掉其他人)
- 给当前元素设置样式(留下我自己)
- 注意顺序不能颠倒,首先干掉其他人,再设置自己
- 首先先排除其他人,然后才设置自己的样式 这种排除其他人的思想我们称排他思想
- 代码案例:
- 如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<script>
var btns = document.getElementsByTagName('button');
/* btns[0].style.backgroundColor = 'pink' */
console.log(btns)
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
for (var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = ''
}
this.style.backgroundColor = 'pink'
}
}
</script>
- 排他算法升级:
- 利用记录上一次元素的索引锁定上一次点击的元素,在这次点击元素的时候,去掉上一次的样式【精准定位到上一个事件源的索引,然后直接修改】:
- 思路:
- 定义一个记录索引的变量index
- 给每个元素对象设置index属性,让其属性值对应元素索引号
- 点击单个元素后记录这个元素对象的index属性值,将其赋值给记录索引号的变量index
- 案例实现:
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<script>
var btns = document.getElementsByTagName('button');
var len = btns.length
var index = 0
for (var i = 0; i < len; i++) {
btns[i].index = i;
btns[i].onclick = function () {
btns[index].style.background = ''
this.style.backgroundColor = 'blue'
index = this.index
}
}
console.log(btns)
</script>
- 百度换肤案例:
- 案例分析:
- 这个案例练习的是给一组元素注册事件
- 给4个小图片利用循环注册点击事件
- 当我们点击了这个图片,让我们页面背景改为当前的图片
- 核心算法:把当前图片的src路径取过来,给body做背景即可
- 案例代码实现:
- 案例分析:
<ul class="box">
<li>
<img src="images/hf1.jpg" alt="">
</li>
<li>
<img src="images/hf2.jpg" alt="">
</li>
<li>
<img src="images/hf3.jpg" alt="">
</li>
<li>
<img src="images/hf4.jpg" alt="">
</li>
</ul>
<script>
var boxs = document.getElementsByClassName('box');
var lis = boxs[0].getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
var src = this.getElementsByTagName('img')[0].src
document.body.style.backgroundImage = 'url(' + src + ')'
}
}
</script>
- 表格隔行变色
- 案例分析:
- 用到新的鼠标事件 鼠标经过onmouseover 鼠标离开onmouseout
- 核心思路:鼠标经过tr行,当前的行变背景颜色,鼠标离开去掉当前背景颜色
- 注意:第一行(thead里面的行)不需要变换颜色,因此我们获取的是tbody里面的行
- 案例代码实现:
- 案例分析:
<tbody>
<tr>
<td>003526</td>
<td>农银金融3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.075</td>
<td>+0.047%</td>
</tr>
<tr>
<td>003526</td>
<td>农银金融3个月定期开放债券</td>
<td>1.075</td>
<td>1.079</td>
<td>1.075</td>
<td>+0.047%</td>
</tr>
</tbody>
<script>
var tbodys = document.getElementsByTagName('tbody');
var trs = tbodys[0].getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++) {
trs[i].onmouseover = function () {
/* 排他思想实现隔行变色for (var i = 0; i < trs.length; i++) {
trs[i].className = 'transp'
} */
this.className = 'pinks';
}
trs[i].onmouseout = function () {
for (var i = 0; i < trs.length; i++) {
this.className = ''
}
}
}
</script>
- 表单全选取消全选案例:
- 案例分析:
- 全选和取消全选做法:让下面所有复选框的checked属性(选中状态)跟随全选按钮即可
- this.checked它可以得到当前复选框的选中状态,如果是true就是选中,如果是false就是未选择
- 设置 表单元素对象.checked=true 可以让其被选中
- 设置表单元素对象.checked=false可以让其不被选中
- 下面复选框需要全部选中,上面全选按钮才能选中做法:给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没有选中的,如果有一个没选中,上面全选按钮就不选中。
- 全选和取消全选做法:让下面所有复选框的checked属性(选中状态)跟随全选按钮即可
- 案例代码实现:
- 案例分析:
<script>
var ipts = document.querySelectorAll('input');
ipts[0].onclick = function () {
console.log(this.checked)
console.log(this.name)
for (i = 1; i < ipts.length; i++) {
ipts[i].checked = this.checked
}
}
for (var i = 1; i < ipts.length; i++) {
ipts[i].onclick = function () {
//flag控制全选按钮是否被选中
var flag = true;
for (var i = 1; i < ipts.length; i++) {
if (ipts[i].checked != true) {
flag = false
break;
}
}
ipts[0].checked = flag
}
}
/* for (i = 1; i < ipts.length; i++) {
ipts[i].onclick = function () {
if (ipts[1].checked === true && ipts[2].checked === true && ipts[3].checked === true && ipts[4].checked === true) {
ipts[0].checked = true
console.log('全选')
} else {
ipts[0].checked = false
}
}
}
*/
</script>
- 判断下面复选框是否全部选中的代码:
- 第一步:获取下面所有的复选框,假设命名为j_tbs
- 第二步:遍历所有复选框,只要有一个没被选中
if(!j_tbs[i].checked){
}
- 自定义属性操作:
- 获取属性值:
- 语法一:element.属性 获取内置属性值
- 元素本身自带的属性
- 语法二:element.getAttribute(‘属性’) ; 主要获得自定义的属性(标准)
- 我们程序员自定义的属性
- 语法一:element.属性 获取内置属性值
- 我们程序员自己定义的属性称为自定义属性
- 设置属性值:
- 语法一:element.属性 = ‘值’ 设置内置属性值
- class属性特殊,需要些className
- 语法二:element.setAttribute(‘属性’,’值’); 设置自定义属性值
- class属性还是写class,没有语法一中的特殊情况
- 语法一:element.属性 = ‘值’ 设置内置属性值
- 移除属性:
- element.removeAttribute(‘属性’);
- 获取属性值:
- element.属性和element.getAttribute(‘属性’)的区别
- element.属性 获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’) ; 主要获得自定义的属性(标准)
- 更改元素类名:
- 语法一:element.className=’类名’
- 和设置属性值有一点区别
- 语法二:element.setAttribute(‘class’,’类名’)
- 语法一:element.className=’类名’
- tab栏切换
- 案例分析:
- Tab栏切换有2个大模块
- 上的模块选项卡,点击某一个,当前这个底色会是红色,其余不变(排他思想)修改类名的方式
- 下面的模块内容,会跟着上面的选项卡变化,所以下面模块变化写到点击事件里面
- 规律:下面的模块显示内容和上面的选项卡一一对应,相匹配。
- 核心思路,给上面的模块选项卡tab_list里面的所有小li添加自定义属性(索引号),属性值从0开始编号,让我们知道选中了哪个小li
- 当我们点击tab_list里面的某个小li,让tab_list里面的某个小li,让tab_con里面对应序号的内容显示,其余隐藏(排他思想)
- 代码案例实现:
- 案例分析:
<div id="containner">
<ul class="containner-hd">
<li>商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价</li>
<li>手机社区</li>
</ul>
<ul class="containner-bd">
<li>商品介绍模块</li>
<li>规格与包装模块</li>
<li>售后保障模块</li>
<li>商品评价模块</li>
<li>手机社区模块</li>
</ul>
</div>
<script>
var hd_lis = document.getElementsByClassName('containner-hd')[0].getElementsByTagName('li');
var bd_lis = document.getElementsByClassName('containner-bd')[0].getElementsByTagName('li');
/* console.log(bd_lis) */
for (var i = 0; i < hd_lis.length; i++) {
hd_lis[i].setAttribute('index', i);
hd_lis[i].onclick = function () {
//获取索引值
var index = this.getAttribute('index');
console.log(index)
for (var i = 0; i < hd_lis.length; i++) {
hd_lis[i].className = ''
bd_lis[i].style.display = 'none'
}
this.className = 'red';
bd_lis[index].style.display = 'block'
}
}
</script>
- H5自定义属性
- 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
- 自定义属性获取是通过getAttribute(‘属性’)获取
- 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
- H5给我们新增了自定义属性:
- H5规定自定义属性data-开头做为属性名并且赋值。
- 比如:<div data-index='1'></div>
- 或者使用JS设置
- element.setAttribute(‘data-index’, 2)
- H5规定自定义属性data-开头做为属性名并且赋值。
- 获取H5自定义属性
- 语法一:
- 兼容性获取:element.getAttribute(‘data-index’)
- 语法二:
- H5新增element.dataset.自定义属性名【去掉data-,自定义属性名采取小驼峰命名法。元素对象里面的属性名必须以data-开头】
- 比如:H5新增element.dataset.index或者element.dataset[‘index’] ie11才开始支持(此方式的元素对象有data-index属性)【自定义属性以data-开头】
- 如果自定义属性名里面有多个-连接的单词,我们获取的时候采取小驼峰命名法
- dataset是一个集合里面存放了所有以data开头的自定义属性
- H5新增element.dataset.自定义属性名【去掉data-,自定义属性名采取小驼峰命名法。元素对象里面的属性名必须以data-开头】
- 语法一:
- 节点操作
- 为什么学节点操作
- 获取元素通常使用两种方式:
- 利用DOM提供的方法获取元素
- document.getElementById()
- document.getElementsByTagName()
- document.querySelector等
- 逻辑不强,繁琐
- 利用节点层级关系获取元素
- 利用父子兄弟节点关系获取元素
- 逻辑性强,但是兼容性稍差
- 利用DOM提供的方法获取元素
- 以上两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单
- 获取元素通常使用两种方式:
- 节点概述:
- 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示
- HTML DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除
- 一般地,节点至少拥有nodeType(节点类型) 、nodeName(节点名称) 和nodeValue(节点值)这三个基本属性。
- nodeType:
- 元素节点nodeType为1
- 属性节点nodeType为2
- 文本节点nodeType为3(文本节点包含文字、空格、换行等)
- 注释节点nodeType为8
- document文档节点nodeType为9
- 文档类型节点nodeType为10
- DocumentFragment文档片段节点,在文档中没有对应的标记,nodeType为11
- nodeName:
- 元素节点的标签名,以大写字母的形式表示,只读不能修改
- nodeValue:
- 文本节点和注释节点的内容,可读可写
- nodeType:
- 节点的类型(最有用的),帮助我们区分节点只读
- attributes元素节点的属性集合(只能修改属性值)。name属性名。value属性值
- nodeType:
- 我们在实际开发中,节点操作主要操作的是元素节点
- 节点层级:
- 利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
- 父级节点
- node.parentNode【兼容所有浏览器】
- 父级节点
- 利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
- 为什么学节点操作
node相对于前面的element元素对象,得到的是离元素最近的父级节点(父级元素对象),如果找不到就返回null
parentNode属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的节点没有父节点则返回null
- node.parentElement【ie9一下不兼容】
父元素节点
所有元素最顶层的父元素节点是html,html父元素节点【parentElement】是null,父节点【parentNode】是document
- parentNode和parentElement除了顶层节点不一样,其他节点都是一样的
- 子节点
- parentNode.childNodes 【标准】
返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用childNodes
parnetNode.childNodes[索引号].nodeType==1
判断子节点是否为元素节点
- parentNode.children 【非标准】
parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(这个是我们重点掌握的)
虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
children获取所有的子元素节点 也是我们实际开发常用的
- parentNode.firstChild
firstChild返回第一个子节点(不管是文本节点还是元素节点,都会给你拿到),找不到则返回null,同样,也是包含所有的节点。
- parentNode.firstElementChild
返回第一个子元素节点【有兼容性问题,IE9以上才支持】
- parentNode.lastChild
firstChild返回最后一个子节点(不管是文本节点还是元素节点,都会给你拿到),找不到则返回null,同样,也是包含所有的节点
- parentNode.lastElementChild
返回最后一个子元素节点【有兼容性问题,IE9以上才支持】
- 实际开发中,firstChild和lastChild包含其他节点,操作不方便,而firstElementChild和lastElementChild又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
- 解决方案:既没有兼容性问题,又返回第一个子元素和最后一个子元素
- 元素对象.children[0]
- 返回第一个子元素
- 元素对象.children[元素对象.children.length-1]
- 返回最后一个子元素
- 元素对象.children[0]
- 解决方案:既没有兼容性问题,又返回第一个子元素和最后一个子元素
- 兄弟节点
- node.nextSibling
- nextSibling返回当前元素的下一个兄弟节点(包含元素节点或者文本节点等等)【下面的第一个兄弟节点】,找不到则返回null。同样,也是包含所有的节点。
- node.previousSibling
- previousSibling返回当前元素上一个兄弟节点【上面第一个紧邻的兄弟节点】,找不到则返回null。同样,也是包含所有的节点。
- node.nextElementSibling
- nextElementSibling返回当前元素的下一个兄弟元素节点(包含元素节点或者文本节点等等),找不到则返回null。同样,也是包含所有的节点【有兼容性问题,IE9以上才支持】
- node.previousElementSibling
- previousElementSibling返回当前元素上一个兄弟元素节点,找不到则返回null。【有兼容性问题,IE9以上才支持】
- 如何解决上面两个兄弟节点兼容性问题:
- 自己封装一个兼容性的函数。代码如下:
- function getNextElementSibling(element) {
- var el = element;
- while (el = el.nextSibling) {
- if (el.nodeType === 1) {
- return el;
- }
- }
- return null;
- }
- 自己封装一个兼容性的函数。代码如下:
- node.nextSibling
- 节点操作:
- 创建节点
- 语法一:document.createElement(‘tagName’)
- document.createElement()方法创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
- 语法一:document.createElement(‘tagName’)
- 添加节点
- 语法一:node.appendChild(child)
- node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。类似于CSS里面的after伪元素
- node为父节点,child为子节点,在父元素里面最后一个元素后追加节点
- node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。类似于CSS里面的after伪元素
- 语法二:node.insertBefore(child,指定元素)
- node为父节点,child为创建的子节点,在父节点的指定元素前面加入创建的子节点
- child如果是DOM树上已经存在的节点,则会删除原来节点的位置,插入到新位置。
- 语法一:node.appendChild(child)
- 创建节点
- 发布留言案例:
- 案例分析:
- 核心思路:点击按钮之后,就动态创建一个li,添加到ul里面。
- 创建li的同时,把文本域里面的值通过li.innerHTML赋值给li
- 如果想要新的留言后面显示就用appendChild如果想要前面显示就用insertBefore
- 案例代码实现:
- 案例分析:
<textarea name="" id="" cols="30" rows="10" placeholder="请输入评论"></textarea>
<button>发布</button>
<button>发布并置顶评论</button>
<ul class="more">
<li>我是第一个发言的帅哥,该你发言了</li>
</ul>
<script>
//获取元素
var text = document.querySelector('textarea');
var more = document.querySelector('ul')
//获取元素节点函数
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el
}
}
return null
}
var btn0 = getNextElementSibling(text);
var btn1 = getNextElementSibling(btn0);
console.log(text.value)
console.log(btn0)
console.log(btn1)
//注册事件
btn0.onclick = function () {
if (text.value == '') {
alert('你还没输入')
} else {
//创建元素
var creatLis = document.createElement('li')
//添加元素
more.appendChild(creatLis);
//添加元素的里面放入内容
creatLis.innerHTML = text.value
}
}
btn1.onclick = function () {
if (text.value == '') {
alert('你还没输入')
} else {
var oneLi = more.children[0]
//创建元素
var creatLis = document.createElement('li')
//添加元素
more.insertBefore(creatLis, oneLi);
//添加元素的里面放入内容
creatLis.innerHTML = text.value
}
}
</script>
- 删除节点
- node.removeChild(child)
- node为父节点,child为子节点
- node.removeChild()方法从DOM中删除一个子节点,返回删除的节点。
- 删除留言案例:
- 案例分析:
- 当我们把文本域里面的值赋值给li的时候,多添加一个删除的链接
- 需要把所有的链接获取过来,当我们点击当前的链接的时候,删除当前链接所在的li
- 阻止链接跳转需要添加javascript:void(0)或者javascript:;
- 案例分析:
- node.removeChild(child)
- 复制节点(克隆节点)
- node.cloneNode()
- node.cloneNode()方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点
- 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点(不克隆内容和其他标签)
- 如果括号参数为true,则是深拷贝,即既复制标签,又复制标签里面的内容
- 复制节点相当于创建了一个复制节点,同样需要有添加节点操作(即告诉浏览器将复制的节点放在什么位置)
- 表格动态数据生成
- 案例分析:
- 因为里面的学生数据都是动态的,我们需要js动态生成,这里模拟数据,自己定义好数据,数据我们采取对象形式存储
- 案例分析:
- 871
- 三种动态创建元素 (相同点:都可以解析标签)
- document.write()
- 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘(在新页面创建内容和标签,当它在事件里面,以前的内容将会全部消失,只有事件触发后事件里面的内容)
- 如果页面文档流加载完毕,再调用这句话会导致页面重绘
- 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘(在新页面创建内容和标签,当它在事件里面,以前的内容将会全部消失,只有事件触发后事件里面的内容)
- element.innerHTML
- 这种方式创建一个元素可以,当需要创建多个相同元素时,有两种方式:
- 是通过拼接字符串的方式创建,非常耗时
- 案例:
- 采取数组形式拼接,结构稍微复杂,但创建多个元素效率更高,比document.createElement()效率还高
- 是通过拼接字符串的方式创建,非常耗时
- 这种方式创建一个元素可以,当需要创建多个相同元素时,有两种方式:
- document.createElement(‘目标标签名’)
- 创建目标标签名的标签,使用标签需要使用父元素名.appendChild(子元素名)
- document.write()
- 三种动态创建元素总结:
- Document.write是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍复杂
- createElement()创建多个元素效率稍低一点点,但是结构更清晰
- 不同浏览器下,innerHTML效率要比creatElement高
- 当我们页面加载完了再去调用我们JS代码:
window.onload = function () {
}
- DOM重点核心
- 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的编程接口。
- 我们获取过来得DOM元素是一个对象(object),所以称为文档对象模型
- W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
- 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口
- 对于HTML,dom使得html形成一颗dom树,包含文档、元素、节点
- 关于dom操作,我们主要针对元素的操作,主要有创建、增、删、改、查、属性操作、事件操作。
- 创建:
- document.write
- innerHTML
- createElement
- 增
- appendChild
- insertBefore
- 删
- removeChild
- 改:主要修改dom元素属性,dom元素的内容、属性,表单的值等
- 修改元素属性:src、href、title等
- 修改普通元素内容:innerTHML、innerText
- 修改表单元素:value、type、disbled等
- 修改元素样式:style、className
- 查:主要获取查询dom的元素
- DOM提供的API方法:getElementById、getElementsByTagName、古老用法 不太推荐
- H5提供的新方法:querySelector、querySelectorAll提倡
- 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)提倡
- 属性操作:主要针对自定义属性
- setAtribute:设置dom的属性值
- getAttribute:得到dom的属性值
- removeAttribute:移除属性
- 事件操作
- 给元素注册事件,采取 事件源.事件类型=事件处理程序
- 创建:
- 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的编程接口。
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发(表单,输入框有了焦点触发) |
onblur | 失去鼠标焦点触发(表单) |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
- 事件高级
- 目标:
- 能够写出元素注册事件的两种方式
- 能够说出删除事件的两种方式
- 能够说出DOM事件流的三个阶段
- 能够利用事件对象完成跟随鼠标案例
- 能够封装阻止冒泡的兼容性函数
- 能够说出事件委托的原理
- 能够说出常用的鼠标和键盘事件
- 目标:
- 注册事件(绑定事件)
- 注册事件概述
- 给元素添加事件,称为注册事件或者绑定事件。
- 注册事件有两种方式:传统方式和方法监听注册方式
- 传统注册方式:
- 利用on开头的事件:例如onclick
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。
- 方法监听注册方式
- W3C标准 推荐方式
- addEventListener()它是一个方法
- IE9之前的IE不支持此方法,可使用attachEvent()代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 传统注册方式:
- 注册事件概述
- addEventListener事件监听方式【DOM2级事件:可以绑定多个事件处理函数,会按照事件绑定的先后顺序执行事件处理函数】
- 语法:
- eventTarget.addEventListener(type,listener[,useCapture])
- eventTarget.addEventListener()方法将指定的监听器注册到eventTarget(监听对象:获取的元素对象)上,当该对象触发指定的事件时,就会执行事件处理函数
- 该方法接收三个参数:
- type:事件类型字符串。比如click、mouseover,注意这里不要带on
- eventTarget.addEventListener(type,listener[,useCapture])
- 语法:
事件侦听注册事件addEventListener里面的事件类型是字符串 必定加引号 而且不带on
同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
- listener: 事件处理函数,事件发生时,会调用该监听函数
可以是一个函数(有名函数或匿名函数),也可以是调用函数名(不需要加小括号)
内部this指向为事件源,即绑定该事件的元素对象
- useCapture: 可选参数,是一个布尔值,默认是false。学完DOM事件流后,我们再进一步学习【是否监听捕获阶段】
true:表示监听捕获阶段
false表示监听冒泡阶段
- IE9之前的IE不支持此方法(移动端经常用此方法)
- attachEvent事件监听方式【DOM2级事件:可以绑定多个事件处理函数,但和addEventListener事件执行顺序相反】
- 语法:
- eventTarget.attachEvent(eventNameWithOn,callback)
- evenTarget.attachEvent()方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
- 该方法接收两个参数:
- eventNameWithOn:事件类型字符串,比如onclick、onmouseover,这里要带on
- callback:事件处理函数,当目标触发事件时回调函数被调用
- eventTarget.attachEvent(eventNameWithOn,callback)
- 语法:
内部this指向window
- IE8及早期版本才支持(了解即可,尽量不用)
- 什么是回调函数:
- 一个被作为参数传递的函数。
- 什么是事件处理模型:
- 事件流就是当你点击了某个元素,单击事件不仅仅发生在这个元素上,你也点击了它的父元素、父元素的父元素、…它的祖先元素,甚至单击了整个页面
- “事件流”描述的是页面上各个元素接收事件的顺序。
- 我们为了描述事件的传播顺序,特意认为规定了两个阶段:捕获阶段、冒泡阶段。点击页面的一个元素,事件在哪个阶段触发,这取决于添加事件监听的方法。
- DOM0级事件绑定,这种事件添加方法,只能监听冒泡阶段,事件的捕获阶段,没有监听成功。
- 冒泡阶段:点击一个元素触发多个事件时,先执行子元素事件,再执行父元素的事件,一层一层向上执行【从小往大查找】
- IE9,chrome里面,事件会冒泡到window对象,而IE6,7,8仅仅冒泡到document对象
- 捕获阶段:点击一个元素触发多个事件时,先执行父元素事件,再执行子元素的事件,一层一层向下执行【从大往下查找】
- 事件源捕获阶段和冒泡阶段同时存在:先执行捕获阶段,再执行冒泡阶段。
- 冒泡阶段:点击一个元素触发多个事件时,先执行子元素事件,再执行父元素的事件,一层一层向上执行【从小往大查找】
- 注册事件兼容性解决方案:
- 封装一个兼容性函数:
function addEventListener(element, eventName, fn) {
//判断当前浏览器是否支持addEventListener方法
if (element.addEventListener) {
element.addEventListener(eventName, fn);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
//相当于element.onclick=fn;
element['on' + eventName] = fn;
}
}
- 兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器
- 删除事件(解绑事件)【解绑事件一定要保证是同一个元素,同一个事件,同一个事件处理函数】
- 删除事件的方式
- 传统注册方式
- 语法:eventTarget.onclick=null;
- evenTarget即为获取的元素对象
- 语法:eventTarget.onclick=null;
- 方法监听注册方式
- 语法1:eventTarget.removeEventListener(type,listener[,useCapture]);
- 注册事件是addEventListener事件监听方式的删除事件方式
- 该方法接收三个参数:
- 语法1:eventTarget.removeEventListener(type,listener[,useCapture]);
- 传统注册方式
- 删除事件的方式
type:事件类型字符串。比如click、mouseover,注意这里不要带on
事件侦听注册事件addEventListener里面的事件类型是字符串 必定加引号 而且不带on
同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
listener: 事件处理调用函数名(不需要加小括号),事件发生时,会调用该监听函数
useCapture: 可选参数,是一个布尔值,默认是false。学完DOM事件流后,我们再进一步学习
- 语法2:eventTarget.detachEvent(type,事件调用函数名)
- 注册事件是attachEvent事件监听方式的删除事件
- 语法2:eventTarget.detachEvent(type,事件调用函数名)
- 删除事件兼容性解决方案:
function removeEventListener(element, eventName, fn) {
//判断当前浏览器是否支持removeEventListener方法
if (element.removeEventListener) {
element.removeEventListener(eventName, fn);
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
}
- DOM事件流
- 事件流描述的是从页面中接收事件的顺序。
- 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
- DOM事件流分为3个阶段:
- 捕获阶段(从大往小查的阶段)
- 当前目标阶段
- 冒泡阶段(从小往大查的阶段)
- 注意:
- JS代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent只能得到冒泡阶段。
- addEventListener(type,listener,useCapture)第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
- 有些事件是没有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave
- 实际开发中,我们很少使用事件捕获,我们更关注事件冒泡。
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事情,我们后面讲解。
- 事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
- 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程
- 事件对象:
- event就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
- 这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
- 当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。
- 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
- 事件对象 是 我们事件的一系列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标呀,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了哪个键
- 这个事件对象我们可以自己命名 比如event、evt、e等
- 什么是事件对象:
- 官方解释:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
- 简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
- 比如:
- 谁绑定了这个事件
- 鼠标触发事件的的话,会得到鼠标的相关信息,如鼠标位置。
- 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
- 比如:
- 事件对象也有兼容性问题(比如ie678 通过window.event)
- 例如:
- var div=document.querySelector('div')
- 例如:
div.onclick=function(ev){}
- ev就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
ev=event || window.event
- 881
- 事件对象的兼容性方案:
- 事件对象本身的获取存在兼容性问题:
- 标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到。
- 在IE6~8,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找
- 解决:
- e = e || window.event;
- 事件对象本身的获取存在兼容性问题:
- 事件对象上储存的常用信息:
- clientX/clientY:鼠标距离浏览器左上角的水平/竖直距离
- pageX/pageY:鼠标距离页面左上角的水平/竖直距离
- offsetX/offsetY:鼠标距离事件的元素左上角的水平/竖直距离
- layerX/layerY:鼠标距离最近定位父级元素左上角的水平/竖直距离
- screenX/screenY:鼠标距离计算机屏幕左上角的水平/竖直距离
- 事件对象的常见属性和方法
事件对象属性方法 | 说明 |
e.target | 返回触发事件的对象(获取过来的元素,即事件源) 标准【chrome和高版本iE】 |
e.currentTarget | 返回添加事件的对象【等价于事件处理函数里的this】 |
e.srcElement | 返回触发事件的对象【事件源,低版本IE】 非标准 ie6~8使用 |
e.type | 返回事件的类型 比如click mouseover 不带on |
e.cancelBubble | 该属性阻止冒泡 非标准 ie6~8使用 |
e.returnValue | 该属性 阻止默认事件(默认行为) 非标准ie6~8使用 比如不让链接跳转 |
e.preventDefault() | 该方法 阻止默认事件(默认行为) 标准 比如不让链接跳转 让提交按钮不提交 |
e.stopPropagation() | 阻止冒泡 标准【阻止事件流的传播: 1.冒泡阶段: A.只会执行添加事件的对象【即父元素的事件不会被触发】 B.父元素是冒泡阶段的可以继续设置事件 2.捕获阶段: A.设置该方法后,子元素是捕获阶段的将设置不了事件【设置事件无效】 】 |
- e为事件处理函数里面的形参
- 事件处理函数内
- this返回的是绑定事件的对象(元素)
- e.target返回的是触发事件的对象(元素)
- 谁触发了这个事件 指向我们当前鼠标在的元素
- this和e.target的区别:
- e.target点击了哪个元素,就返回哪个元素
- this 哪个元素绑定了这个点击事件,那么就返回谁
- e.preventDefault();普通浏览器阻止默认行为方法
- e.returnValue; 低版本浏览器阻止默认行为属性
- e.returnValue=false;【和return false等价】
- return false;也能阻止默认行为,没有兼容性问题
- 特点:return后面的代码不再执行了,而且只限于传统的注册方式
- 了解跟this有个非常相似的属性 currentTarget
- ie678不认识currentTarget
- 阻止事件冒泡
- 事件冒泡:开始时由最基本的元素接收,然后逐级向上传播到DOM最顶层节点
- 事件冒泡本身的特性,会带来坏处,也会带来好处,需要我们灵活掌握
- 阻止事件冒泡的两种方式
- 标准写法:利用事件对象里面的stopPropagation()方法
- E.stopPropagation()
- 非标准:IE6~8利用事件对象cancelBubble属性
- window.event.cancelBubble = true;
- 标准写法:利用事件对象里面的stopPropagation()方法
- 阻止事件冒泡的兼容性解决方案:
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
- 事件委托(代理、委派)
- 事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握,生活中有如下场景
- 事件委托也称为事件代理,在Jquery里面称为事件委派
- 事件委托的原理
- 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
- 父节点设置事件监听,然后利用事件对象的target来找到当前点击的元素(即父节点内的子节点),因为触发该子节点。事件会冒泡到父节点上,父节点有注册事件,就会触发事件监听器
- 为了防止点击父节点的时候出现和子元素一样的样式变化,需要设置判断或节流:
- 父节点设置事件监听,然后利用事件对象的target来找到当前点击的元素(即父节点内的子节点),因为触发该子节点。事件会冒泡到父节点上,父节点有注册事件,就会触发事件监听器
- 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
如果是子元素才设置子元素样式【用e.target.nodeName判断是否是子元素】或如果不是子元素直接节流(return)
设置样式:e.target.style.background=’pink’
- 事件委托的作用
- 我们只操作了一次DOM,提高了程序的性能。
- 事件委托的作用
- 常用的鼠标事件
鼠标事件 | 触发条件 |
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发(表单,输入框有了焦点触发) |
onblur | 失去鼠标焦点触发(表单) |
onmousemove | 鼠标移动触发(只要鼠标移动1px距离就会触发事件) |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
- 禁止鼠标右键菜单
- contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
- 代码案例:
- contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
- 禁止鼠标右键菜单
fa.addEventListener('contextmenu', function (e) {
e.preventDefault();
})
- 选中部分元素内容 鼠标右键将不起作用
- 禁止鼠标选中(selectstart 开始选中)
- 代码案例实现:
fa.addEventListener('selectstart', function (e) {
e.preventDefault();
})
- 鼠标将无法选中内容
- 鼠标事件对象
- event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent.
鼠标事件对象 | 说明 |
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标IE9+支持 |
e.pageY | 返回鼠标相对于文档页面的Y坐标IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
- 图片跟随鼠标移动案例:
- 案例分析:
- 鼠标不断的移动,使用鼠标移动事件:mousemove
- 在页面中移动,给document注册事件
- 图片要移动距离而且不占位置,我们使用绝对定位即可
- 核心原理:每次鼠标移动,我们都会获得最好的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片
- 案例代码实现:
- 案例分析:
var img = document.querySelector('img')
document.addEventListener('mousemove', function (e) {
img.style.left = e.clientX + 'px'
img.style.top = e.clientY + 'px'
})
- 千万不要忘记给left和top加px单位
- 常用的键盘事件
- 事件除了使用鼠标触发,还可以使用键盘触发。
键盘事件 | 触发条件 |
onkeyup | 某个键盘按键被松开时触发(需要鼠标先点击一下事件源本身) |
onkeydown | 某个键盘键被按下时触发(需要鼠标先点击一下事件源,这时按住键盘任意键都可以触发该事件,但是只要不松手,会一直触发) |
onkeypress | 某个键盘按键被按下时 触发 但是它不识别功能键 比如CTRL shift箭头等 |
- 上面三个事件的执行顺序:keydown 然后keypress 最后keyup
- 注意:
- 如果使用addEventListener不需要加on
- onkeypress和前面2个的区别是,它不识别功能键
- 三个事件的执行顺序:keydown 然后keypress 最后keyup
- onkeydown和onkeyup不区分字母大小写(所有字母当小写来看,它的keyCode也是小写ASCLL值),onkeypress区分字母大小写
- 在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键),keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCLL值
- 键盘事件对象
键盘事件对象属性 | 说明 |
keyCode | 返回该键的ASCLL值 |
- 我们可以利用keyCode返回的ASCLL码值 来判断用户按下了哪个键(键盘事件才有的属性值【onkeyup onkeydown onkeypress】)
- 也可以利用e.key=键名字符串来判断用户按下了哪个键。
- 案例:
var btns = document.querySelectorAll('button');
btns[0].onkeypress = function (e) {
console.log(e.keyCode)
}
- 京东表单获取焦点案例:
- 案例分析:
- 核心思路:检测用户是否按下了s键,如果按下了s键,就把光标定位到搜索框里面
- 使用键盘事件对象里面的keyCode判断用户按下的是否是s键
- 搜索框获得焦点:使用js里面的focus()方法
- 案例代码实现:
- 案例分析:
var ipt = document.querySelector('input')
document.addEventListener('keydown', function (e) {
console.log('你好')
if (e.keyCode === 83) {
ipt.focus();
}
})
- 京东快递查询单号案例:
- 案例分析:
- 快递单号输入内容时,上面的大号字体盒子(con)显示(这里面的字号更大)
- 表单检测用户输入:给表单添加键盘事件
- 同时把快递单号里面的值(value)获取过来赋值给con盒子(innerText)作为内容
- 如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子
- 注意:keydown和keypress在文本框里面的特点:它们两个事件触发的时候,文字(表单里面的内容)还没有落入文本框(value)中【相当于,在表单中输入数据后,表单里面实际的内容值比表单的value值多一个字符】。
- Keyup事件触发的时候,文字已经落入文本框里面了。【相当于,在表单中输入数据后,表单里面实际的内容值和表单的value值一样】
- 当我们失去焦点,就隐藏这个con盒子
- 当我们获得焦点,并且文本框的内容不为空,就显示这个con盒子
- 代码案例实现:
- 案例分析:
var ipt = document.querySelector('input')
document.addEventListener('keyup', function (e) {
console.log('你好')
if (e.keyCode === 83) {
ipt.focus();
}
if (ipt.value !== '') {
console.log('value不为空')
con.style.display = 'block'
con.innerText = ipt.value
}
})
ipt.addEventListener('blur', function () {
con.style.display = 'none'
})
ipt.addEventListener('focus', function () {
if (this.value !== '') {
console.log(1)
con.style.display = 'block'
}
})
- 捕获错误:
- 语法:
- try{
- 语法:
以后可能出现错误的代码
}catch(err){
//可以打印这个错误信息
}
- err:接收错误信息的参数
- 它不会终止程序继续运行,这个语法下面的代码会正常运行。
- BOM浏览器对象模型
- 目标:
- 能够说出什么是BOM
- 能够知道浏览器的顶级对象window
- 能够写出页面加载事件以及注意事项
- 能够写出两种定时器函数并说出区别
- 能够说出JS执行机制
- 能够使用location对象完成页面之间的跳转
- 能够知晓navigator对象涉及的属性
- 能够使用history提供的方法实现页面刷新
- 目标:
- BOM概述
- 什么是BOM
- BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
- BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
- BOM缺乏标准,JavaScript语法的标准化是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分。
- BOM的构成:
- BOM比DOM更大,它包含DOM
- window对象是浏览器的顶级对象[Global],它具有双重角色
- 它是JS访问浏览器窗口的一个接口
- alert()弹出一个窗口,无返回值
- confirm()弹出一个窗口的同时,增加了两个选择按钮,返回值为布尔值
- prompt()在confirm的基础上,增加了输入框供用户输入内容,返回值为用户输入的内容
- open(‘新页面url地址’,’打开方式’) ==> open(‘www.baidu.com’,’_blank’)
- 它是JS访问浏览器窗口的一个接口
- 什么是BOM
打开方式:
_blank:新页面打开,会打开多个新页面【重复打开】
_self:当前页面打开
_new:新页面打开,新页面只会有一个【不会重复打开】
常用于事件处理函数里面
- 它是一个全局对象。定义在全局作用域中的变量,函数都会变成window对象的属性和方法
- 在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、propmpt()等
- 注意:window下的一个特殊属性window.name
- 它是一个全局对象。定义在全局作用域中的变量,函数都会变成window对象的属性和方法
- DOM和BOM
- DOM:
- 文档对象模型
- DOM就是把文档当作一个对象来看待
- DOM的顶级对象是document
- DOM主要学习的是操作页面元素
- DOM是W3C标准规范
- BOM
- 浏览器对象模型
- 把浏览器当作一个对象来看待
- BOM的顶级对象是window
- BOM学习的是浏览器窗口交互的一些对象
- BOM是浏览器厂商在各自浏览器上定义的,兼容性较差
- DOM:
- BOM的元素构成:
- window:
- document
- location
- navigation
- screen
- history
- window:
- window对象的常见事件
- 窗口加载事件
- 语法:
- 语法一:window.onload = function () { }
- 语法二: window.addEventListener('load', function () { })
- 语法三:
- 语法:
- 窗口加载事件
document.addEventListener('DOMContentLoaded', function () {})
- window.onload是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等),就调用的处理函数。
- DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等(ie9以上才支持)。
- 如果页面的图片很多的话,从用户访问到onload触发可能需要较长的时间,交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded事件比较合适。
- 注意:
- 有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面全部加载完毕,再去执行处理函数。
- window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准
- 如果使用addEventListener则没有限制
- DOMContentLoaded事件和load事件的区别
- DOMContentLoaded是DOM加载完毕,不包含图片 falsh css等就可以执行 加载熟读比load更快一些
- 调节窗口大小事件
- 语法:
- 语法一: window.onresize=function(){}
- 语法二:window.addEventListener('resize',function(){})
- window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数
- 注意:
- 语法:
只要浏览器窗口大小发生像素变化,就会触发这个事件。
我们经常利用这个事件完成响应式布局。window.innerWidth当前屏幕的宽度
- 定时器
- window对象给我们提供了2个非常好用的方法-定时器
- 两种定时器
- 延迟定时器:setTimeout();
- 循环定时器:setInterval();
- 定时器返回值:
- 返回值为一个唯一数值【通常叫id值】,可以通过这个id关闭这个定时器。
- 从1开始,依次增加【定时器的id依次递增,从1开始,每个定时器的id唯一。】
- 返回值为一个唯一数值【通常叫id值】,可以通过这个id关闭这个定时器。
- 关闭定时器:
- clearInterval(id)
- clearTimeout(id)
- 两个关闭定时器的方法都可以关闭setInterval和setTimeout打开的定时器,但是一般clearInterval用于关闭setInterval打开的定时器,clearTimeout用于关闭setTimeout打开的定时器。
- 定时器的参数:
- 第一个参数:
- 执行的函数
- 字符串:字符串会被当成js语句的字符串。
- 第二个参数:
- 延迟的时间,为毫秒数,是数字
- 表达式能够自动计算
- 第三个及以上的参数,都将会作为第一个参数函数的实参【第一个参数函数有形参就会将实参传递过去】
- 第一个参数:
- setTimeout()定时器
- 语法:window.setTimeout(调用函数, [延迟的毫秒数]);
- setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。【只执行一次】
- 这个延时时间单位是毫秒 但是可以省略,如果省略默认的是0
- 这个调用函数可以直接写函数 还可以写 函数名 或者采取字符串(即‘函数名()’) 三种形式。第三种不推荐
- 延时时间到了,就去调用这个回调函数,只调用一次,就结束了这个定时器
- 这个window在调用的时候可以省略
- 例如:setTimeout(function(){}, 2000);
- 2000单位是毫秒
- 例如:setTimeout(function(){}, 2000);
- 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
- setTimeout()这个调用函数我们也称为回调函数callback
- 普通函数是按照代码顺序直接调用,而这个函数,需要等待时间,时间到了才调用这个函数,因此称为回调函数
- 简单理解:回调,就是回头调用的意思。上一件事干完,再回头调用这个函数
- 以前我们讲的element.onclick=function(){}或者element.addEventListener(‘click’,fn);里面的函数也是回调函数。
- 语法:window.setTimeout(调用函数, [延迟的毫秒数]);
- 5秒后自动关闭广告案例:
- 案例分析:
- 核心思路:5秒之后,就把这个广告隐藏起来
- 用定时器setTimeout
- 案例代码实现:
- 案例分析:
var img = document.querySelector('img')
setTimeout(function () {
img.style.display = 'none';
}, 5000)
- 停止setTimeout()定时器
- 语法:window.clearTimeout(timeoutID)
- clearTimeout()方法取消了先前通过调用setTimeout()建立的定时器。
- timeoutID为保存 设置定时器的变量(即定时器的标识符)
- 注意:
- window可以省略
- clearTimeout清理setTimeout定时器一定要在执行前清理,因为它只会执行一次。,执行完以后本身就没什么意义了。
- 案例:
- 语法:window.clearTimeout(timeoutID)
var btns = document.querySelectorAll('button')
var open = window.setTimeout(function () {
console.log('打开定时器')
}, 2000)
btns[0].addEventListener('click', function () {
window.clearTimeout(open);
})
- setInterval()定时器
- 语法:window.setInterval(回调函数,[间隔的毫秒数]);
- setInterval()方法重复调用一个函数,每隔这个时间就去调用一次回调函数。
- 这个间隔的毫秒数单位是毫秒 但是可以省略,如果省略默认的是0
- 这个调用函数可以直接写函数 还可以写 函数名 或者采取字符串(即‘函数名()’) 三种形式。第三种不推荐
- 这个window在调用的时候可以省略
- 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。【内部this指向window】
- 语法:window.setInterval(回调函数,[间隔的毫秒数]);
- setTimeout和setInterval的区别:
- setTimeout延时时间到了,就去调用这个回调函数,只调用一次,就结束了这个定时器
- setInterval每隔这个延时时间,就去调用这个回调函数,会调用很多次。重复调用这个函数。
- 秒杀案例:
- 案例分析:
- 这个倒计时是不断变化的,因此需要定时器来自动变化(setInterval)
- 三个黑色的盒子,分别存放时分秒
- 三个黑色盒子利用innerHTML放入计算的小时 分钟 秒数
- 第一次执行也是间隔毫秒数,因此刚刷新页面会有空白
- 最好采取封装的方式,这样可以先调用一次这个函数,防止刚开始刷新页面有空白问题
- 代码实现案例:
- 案例分析:
function fn() {
var hours = document.getElementsByClassName('hour')
var minutes = document.getElementsByClassName('minute')
var seconds = document.getElementsByClassName('second')
var time = new Date();
var hour = time.getHours();
var minute = time.getMinutes();
var second = time.getSeconds();
hour = hour < 10 ? '0' + hour : hour
hour = hour.toString()
hours[0].innerHTML = hour
minute = minute < 10 ? '0' + minute : minute
minute = minute.toString()
minutes[0].innerHTML = minute
second = second < 10 ? '0' + second : second
second[0] = second.toString()
seconds[0].innerHTML = second
}
fn();
window.setInterval(function () {
fn();
}, 1000)
- 停止setInterval()定时器
- window.clearInterval(intervalID);
- clearInterval()方法取消了先前通过调用setInterval()建立的定时器。
- 注意:
- window可以省略。
- 里面的参数就是定时器的标识符(即保存定时器的变量)。
- 这个变量用全局变量,声明的时候为null
- 案例代码实现:
<button>开启定时器</button>
<button>关闭定时器</button>
<script>
var btns = document.querySelectorAll('button')
var time = null;
function open() {
time = setInterval(function open() {
console.log('我就是我')
}, 1000)
}
btns[0].addEventListener('click', open)
btns[1].addEventListener('click', closeDown)
function closeDown() {
window.clearInterval(time)
}
</script>
- 设表先关:
- 你开启一个定时器之前先关闭之前的定时器。【循环定时器不关会一直执行】
- 发送短信案例:
- 案例分析:
- 按钮点击之后,会禁用disabled为true
- 同时按钮里面的内容会变化,注意button里面的内容通过innerHTML修改
- 里面秒数是变化的,因此需要用到定时器
- 如果变量为0说明到了时间,我们需要停止定时器,并且复原按钮初始状态。
- 代码案例实现:
- 案例分析:
手机号码: <input type="number"><button>发送</button>
<script>
var btn = document.querySelector('button')
var time = 3;
btn.addEventListener('click', fn)
function fn() {
var timer = setInterval(function () {
if (time == 0) {
clearInterval(timer)
btn.disabled = false;
btn.innerHTML = '发送'
time = 3
} else {
btn.innerHTML = '还剩下' + time + '秒'
time--
btn.disabled = true
}
}, 1000)
}
</script>
- 定时器:
- this
- this的指向在函数定义的时候是确定不了的,只有函数执行的时候才确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象
- this的指向:
- 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)【定时器中函数中的this也是指向window】
- 方法中的this指向该调用方法的对象【该对象里面会有很多方法】
- 事件中this指向事件源
- this
- JS执行队列:
- JS是单线程
- JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为JavaScript这门脚本语言诞生的使命所致-JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
- 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,这样导致的问题是:如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
- 好处:充分发挥一个线程的潜能,满负荷运转
- 坏处:线程阻塞
- 同步和异步
- 为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
- 同步:
- 前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
- 异步:
- 你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。
- 同步和异步的本质区别:这条流水线上各个流程的执行顺序不同。
- JS是单线程
- JS执行机制:
- 同步和异步
- 同步任务:
- 同步任务都在主线程上执行【排队执行的任务】,形成一个执行线【执行栈】。
- 异步任务:
- JS的异步是通过回调函数实现的。
- 不进入主线程,进入“任务队列“的任务
- 一般而言,异步任务有以下三种类型:
- 普通事件,如click、resize等
- 资源加载,如load、error等
- 定时器,包括setInterval、setTimeout等
- 异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)。
- JS执行机制:
- 先执行执行栈中的同步任务。
- 异步任务(回调函数)放入任务队列中。
- 一旦执行栈中所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。908
- 由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(eventloop)。
- 线程阻塞:
- 前面的任务死循环或则耗时过长导致后面代码不能被执行,这种情况叫做线程阻塞。
- 这样就会出现问题,所以对于像事件,定时器,ajax请求这种非常耗时的程序,浏览器就会开辟其他的线程来处理,所以这些程序我们叫他异步程序。
- 浏览器有三个长驻线程,JS引擎线程,界面的渲染线程,已经浏览器事件触发线程,还有一些执行完就终止的线程,比如HTTP请求线程。
- location对象
- 什么是location对象
- window对象给我们提供了一个location属性用于获取或者设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象。
- URL:
- 统一资源定位符(Uniform Resource Locator,URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
- URL的一般语法格式:
- 什么是location对象
protocol://host[:port]/path/[?query]#fragment
http://wwww.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
protocol | 通信协议 常用的http,ftp,maito等 |
host | 主机(域名)www.itheima.com |
port | 端口号 可选,省略时使用方案的默认端口 如http的默认端口为80 |
path | 路径 由 零或多个‘/’符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数 以键值对的形式,通过&符号分隔开来 |
fragment | 片段 #后面内容 常见于链接 锚点 |
- location对象的属性:
location的对象属性 | 返回值 |
location.href | 获取或者设置 整个URL(可以实现页面跳转) |
location.host | 返回主机(域名)www.itheima.com【地址栏主机名+端口号】 |
location.hostname | 返回主机(地址栏的主机名) |
location.port | 返回端口号 如果末写返回空字符串【地址栏的端口号】 |
location.pathname | 返回路径【地址栏的路径】 |
location.search | 返回参数【地址栏?以及后面的字符串】 |
location.hash | 返回片段 #后面内容 常见于链接 锚点 |
location.reload() | 重新加载,可能是缓存,如果参数为true,表示从服务器重新加载 |
- 重点记住:href和search
- 5秒中之后自动跳转页面:
<button>跳转</button>
<div></div>
<script>
var btn = document.querySelector('button')
var con = document.querySelector('div')
var timer = null;
function fn0() {
timer = 5;
var closeT = setInterval(function () {
if (timer == 0) {
location.href = 'https://www.jd.com/'
} else {
con.innerHTML = '还有' + timer + '秒跳转页面'
timer--
}
}, 1000)
}
btn.addEventListener('click', fn0)
</script>
- 获取URL参数数据
- 案例分析:
- 第一个登录页面,里面有提交表单,action提交到index.html页面
- 第二个页面,可以使用第一个页面的参数,这样实现了一个数据不同页面的传递效果
- 第二个页面之所以可以使用第一个页面的数据,是利用了URL里面的location.search参数
- 在第二个页面中,需要把这个参数提取。
- 第一步去掉?利用substr
- 第二步利用=号分割键和值 split(‘=’)【利用=把字符串分割为数组】
- 代码案例实现:
- Demo36.html代码
- 案例分析:
<form action="demo37.html">
用户名: <input type="text" name="uname" id="">
密码:<input type="password" name="pwd" id="">
<input type="submit" value="登录">
</form>
- 表单中有name属性值才可以提交参数【即用户输入的数据赋值给此name属性值】
- Demo37.html代码
<div></div>
<script>
var d = document.querySelector('div')
var str = location.search.substr('1').split('&')
console.log(str[0].split('=')[1])
var str1 = str[0].split('=')[1]
d.innerHTML = str1 + '欢迎你'
</script>
- location.search返回传递过来的参数
- location对象方法
location对象方法 | 返回值 |
location.assign(‘页面地址’) | 跟href一样,可以跳转页面(也称为重定向页面)[具有后退功能,即可以回到以前的页面] |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钮或者 f5 如果参数为true 强制刷新ctrl+f5 |
- navigator对象
- navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
- 下面前端代码可以判断用户哪个终端打开页面,实现跳转
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|woSBrowser|BrowserNG|Webos|Symbian|windows Phone)/i))) {
window.location.href = ''; //手机端跳转页面
} else {
window.location.href = ''; //电脑端跳转页面
}
- history对象
- window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL
history对象方法 | 作用 |
back() | 可以后退功能(回到上一个页面)【新网页是在当前页面打开的情况才有效】 |
forward() | 前进功能(回到下一个页面)【新网页是在当前页面打开的情况才有效】 |
go(参数) | 前进后退功能 参数如果是1前进1个页面 如果是-1后退一个页面,参数是几,就跳几个页面。 |
- history.length:历史页面个数
- PC端网页特效
- 目标:
- 能够说出常见offset系列属性的作用
- 能够说出常见client系列属性的作用
- 能够说出常见scroll系列属性的作用
- 能够封装简单动画函数
- 能够写出网页轮播图案例
- 目标:
- 元素偏移量offset系列
- offset概述
- offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
- offset系列常用属性:
- offset概述
offset系列属性 | 作用 |
element.offsetParent | 返回作为该元素带有定位的父级元素 如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移(top+margin-top) |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移(left+margin-left) |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
- element.offsetParent和element.parentNode的区别:
- element.offsetParent:返回作为该元素带有定位的父级元素 如果父级都没有定位则返回body
- element.parentNode:返回该元素的亲父级元素
- element.offsetParent和element.parentNode的区别:
- offset和style区别
- offset:
- offset可以得到任意样式表中的样式值
- offset系列获得的数值是没有单位的(是数字型)
- offsetWidth包含padding+border+width
- offsetWidth等属性是只读属性,只能获取不能赋值
- 所以,我们想要获取元素大小位置,用offset更合适
- style:
- style只能得到行内样式表中的样式值(行内样式表中没有的返回空字符串)
- style.width获得的是带有单位的字符串(字符串型)
- style.width是可读写属性,可以获取也可以赋值
- 所以,我们想要给元素更改值,则需要用style改变
- offset:
- 获取鼠标在盒子内的坐标
- 案例分析:
- 我们在盒子内点击,想到得到鼠标距离盒子左右的距离。
- 首先得到鼠标在页面中的坐标(e.pageX e.pageY)
- 其次得到盒子在页面中的距离(box.offsetLeft box.offsetTop)
- 用鼠标距离页面的坐标减去盒子在页面中的距离,得到鼠标在盒子内的坐标
- 如果想要移动以下鼠标,就要获取最新的坐标,使用鼠标移动事件mousemove
- 案例代码实现:
- 案例分析:
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.addEventListener('mousemove', fn)
function fn(e) {
X = e.pageX - this.offsetLeft;
Y = e.pageY - this.offsetTop
this.innerHTML = 'x的坐标是' + X + 'px;y的坐标是' + Y + 'px'
}
</script>
- 模态框拖拽
- 弹出框,我们也称为模态框
- 点击弹出层,会弹出模态框,并且显示灰色半透明的遮挡层
- 点击关闭按钮,可以关闭模态框,并且同时关闭灰色半透明遮挡层
- 鼠标放到模态框最上面一行,可以按住鼠标拖拽模态框在页面中移动。
- 鼠标松开,可以停止拖动模态框移动。
- 案例分析:
- 点击弹出层,模态框和遮挡层就会显示出来display: block;
- 点击关闭按钮,模态框和遮挡层就会隐藏起来display: none;
- 在页面中拖拽的原理:鼠标按下并且移动,之后松开
- 触发事件是鼠标按下mousedown,鼠标移动mousemove 鼠标松开mouseup
- 拖拽过程:鼠标移动过程中,获得最新的值赋值给模态框的left和top值,这样模态框可以跟着鼠标走了
- 鼠标按下触发的事件源是 最上面一行,就是id为title
- 鼠标的坐标前去鼠标在盒子内的坐标,才是模态框正真的位置
- 案例代码实现:
- 弹出框,我们也称为模态框
// 1. 获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
// 2. 点击弹出层这个链接 link 让mask 和login 显示出来
link.addEventListener('click', function () {
mask.style.display = 'block';
login.style.display = 'block';
})
// 3. 点击 closeBtn 就隐藏 mask 和 login
closeBtn.addEventListener('click', function () {
mask.style.display = 'none';
login.style.display = 'none';
})
// 4. 开始拖拽
// (1) 当我们鼠标按下, 就获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function (e) {
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
// (2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值
document.addEventListener('mousemove', move)
function move(e) {
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
// (3) 鼠标弹起,就让鼠标移动事件移除
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
})
})
- 京东放大镜案例:
- 案例分析:
- 整个案例可分为三个功能模块
- 鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏2个盒子功能
- 黄色的遮挡层,大图片跟随移动功能
- 黄色的遮挡层跟随鼠标功能。
- 把鼠标坐标给遮挡层不合适,因为遮挡层坐标以父盒子为准
- 首先是获得鼠标在盒子的坐标
- 之后把数值给遮挡层作为left和top值。
- 此时用到鼠标移动事件,但是在小图片盒子内移动
- 移动黄色遮挡层,大图片跟随移动功能
- 大图片的移动公式:
- 核心思路:
- 父元素设置定位属性,子元素设置绝对定位
- 找到鼠标在父元素中的坐标:
- X=e.pageX-父元素.offsetLeft
- Y=e.pageY-父元素.offsetTop
- 子元素的left为鼠标在父元素中的x坐标
- 子元素的top为鼠标在父元素中的y坐标
- 子元素盒子向左移动自身宽度的一半,让鼠标在子元素的中间:
- 子元素的left变为x-自身宽度的一半【可以写为活得:x-子元素对象.offsetWidth/2】
- 子元素想上移动自身宽度的一半,让鼠标在子元素的中间
- 子元素的top变为y-自身高度的一半
- 代码实现:
- 案例分析:
<div class="box">
<div class="son"></div>
</div>
<script>
var box = document.querySelector('.box')
var son = document.querySelector('.son')
box.addEventListener('mousemove', fn)
function fn(e) {
//获取鼠标在父元素中的坐标
var X = e.pageX - this.offsetLeft;
var Y = e.pageY - this.offsetTop
Xmin = son.offsetWidth / 2;
Ymin = son.offsetHeight / 2;
Xmax = box.offsetWidth - son.offsetWidth / 2
Ymax = box.offsetWidth - son.offsetHeight / 2
//将父元素的坐标给子元素的left和top值
if (X < Xmin) {
son.style.left = 0;
} else if (X >= 0 && X <= Xmax) {
son.style.left = X - son.offsetWidth / 2 + 'px';
} else {
son.style.left = Xmax
}
if (Y < Ymin) {
son.style.top = 0;
} else if (Y >= Ymin && Y <= Ymax) {
son.style.top = Y - son.offsetHeight / 2 + 'px';
} else {
son.style.top = YmaY
}
}
</script>
- 元素可视区client系列
- client翻译过来就是客户端,我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以动态得到该元素的边框大小、元素大小等。
client系列属性 | 作用 |
element.clientTop | 返回元素上边框的大小 |
element.clinetLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区高度,不含边框,返回数值不带单位。 |
- 立即执行函数(自执行函数)【IIFE:immediately-invoked function expression及时调用函数表达式】
- 立即执行函数:不需要调用,立马能够执行的函数。
- 函数表达式才可以加括号调用
- 大部分自执行函数都是匿名函数
- 将函数变为表达式:
- 函数前面加+号或-号或!或~
- 语法一: (function(形参) {})(实参)
- 第二个小括号可以看作调用函数
- 当形参值为实参这个值时,立即执行这个函数
- 语法二:(function(形参) {} (实参))
- 主要作用:创建一个独立的作用域,里面所有的变量都是局部变量,不会有命名冲突的情况
- 当形参值为实参这个值时,立即执行这个函数
- 立即执行函数:不需要调用,立马能够执行的函数。
- dpr:
- 物理像素比
- var dpr = window.devicePixelRatio || 1
- 看当前设备的物理像素比能不能拿到,不能拿到就当1来看
- 下面三种情况都会刷新页面都会触发load事件:
- a标签的超链接
- F5或者刷新按钮(强制刷新)
- 前进后退按钮
- 但是 火狐中,有个特点,有个“往返缓存”,这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。
- 所以此时后退按钮不能刷新页面。
- 此时可以使用pageshow事件来触发。这个事件再页面显示时触发,无论页面是否来自缓存,在重新加载页面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件,注意这个事件给window添加。
- 元素滚动scroll系列
- 元素scroll系列属性
- scroll翻译过来就是滚动的,我们使用scroll系列的相关属性可以动态的得到该元素的大小、滚动距离等。
- 元素scroll系列属性
scroll系列属性 | 作用 |
element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回数值不带单位(当内容区超过元素边框,返回内容区高度) |
- 页面被卷去的头部
- 如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发onscroll事件。(只要滚动条发生变化就会触发onscroll事件)
- 页面被卷去的头部
- 仿淘宝固定右侧侧边栏
- 原先侧边栏是绝对定位
- 当页面滚动到一定位置,侧边栏改为固定定位
- 页面继续滚动,会让返回顶部显示出来
- 案例分析:
- 需要用到页面滚动事件scroll因为是页面滚动,所以事件源是document
- 滚动到某个位置,就是判断页面被卷去的上部值
- 页面被卷去的头部:可以通过window.pageYOffset获得 如果是被卷去的左侧window.pageXOffset
- 注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部则是window.pageYOffset。
- 页面被卷去的头部兼容性解决方案
- 需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
- 声明了DTD,使用document.documentElement.scrollTop
- 即页面中有<!DOCTYPE html>
- 未声明DTD,使用document.body.scrollTop
- 即页面中没有<!DOCTYPE html>
- 新方法window.pageYOffset和window.pageXOffset,IE9支持
- 声明了DTD,使用document.documentElement.scrollTop
- 代码实现:
- 需要注意的是,页面被卷去的头部,有兼容性问题,因此被卷去的头部通常有如下几种写法:
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
}
}
- 使用的时候 getScroll().left
- 三大系列总结:
三大系列大小对比 | 作用 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回值不带单位 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回数值不带单位 |
- 他们的主要用法:
- offset系列经常用于获得元素位置offsetLeft offsetTop
- client经常用于获取元素大小clientWidth clientHeight
- scroll经常用于获取滚动距离scrollTop scrollLeft
- 注意页面滚动的距离通过window.pageXOffset获得
- 他们的主要用法:
- mouseenter和mouseover的区别
- mouseEnter鼠标事件
- 当鼠标移动到元素上时就会触发mouseenter事件
- 类似mouseover,他们两者之间的差别是:
- mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发【自身盒子和子盒子自会有一个触发该事件】
- 之所以这样,就是因为mouseenter不会冒泡
- 跟mouseenter搭配鼠标离开mouseleave同样不会冒泡
- mouseEnter鼠标事件
- 动画函数封装
- 动画实现原理:
- 核心原理:通过定时器setInterval()不断移动盒子位置。
- 实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位,才能使用element.style.left
- 注意函数需要传递2个参数,动画对象和移动到的距离938
- 动画函数给不同元素记录不同定时器
- 如果多个元素都使用这个动画函数,每次都要var 声明定时器。我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)。
- 核心原理:利用JS是一门动态语言,可以很方便的给当前对象添加属性。
- 代码案例实现:
- 动画实现原理:
<button>开始</button>
<div></div>
<script>
var div = document.querySelector('div')
var btn = document.querySelector('button')
btn.addEventListener('click', function () {
animate(div, 400)
})
function animate(obj, target) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
if (div.offsetLeft <= target) {
div.style.left = div.offsetLeft + 1 + 'px'
console.log(1)
} else {
console.log(2)
clearInterval(obj.timer)
}
}, 100)
}
</script>
- 开启定时器之前,需要清除以前的定时器
- 缓动效果原理:
- 缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
- 思路:
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
- 核心算法:(目标值-现在的位置)/10 做为每次移动的距离
- 也叫步长,还可以叫缓动动画公式
- 停止的条件是:让当前盒子位置等于目标位置就停止定时器
- 匀速动画就是 盒子是 当前的位置 + 固定值
- 缓动动画就是 盒子当前的位置 + 变化的值(目标值-现在的位置)/10
- 动画函数添加回调函数
- 回调函数原理:函数作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调
- 动画函数封装到单独JS文件里面
- 因为以后我们经常使用这个动画函数,可以单独封装到一个JS文件里面,使用的时候引用这个JS文件即可。
- 常见网页特效案例:
- 轮播图也称为焦点图,是网页中比较常见的网页特效。
- 功能需求:
- 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
- 点击右侧按钮一次,图片往左播放一张,依次类推
- 点击右侧按钮依次,就让图片滚动一张
- 声明一个变量num,点击一次,自增1,让这个变量乘以图片宽度,就是ul的滚动距离
- 图片无缝滚动原理
- 功能需求:
- 轮播图也称为焦点图,是网页中比较常见的网页特效。
把第一个li复制一份放到ul的最后面
当图片滚动到克隆的最后一张图片时,让ul快速的、不做动画的跳到最左侧:left为0
同时num赋值为0,可以重新开始滚动图片了
图片无缝滚动会出现一个问题:小圆圈是跟着li一起变化的,所以小圆圈会多一个,此时解决的方案是:
克隆第一张图片放在最后面:
var first=ul.children[0].cloneNode(true);
ul.appendChild(first);
- 点击右侧按钮,小圆圈跟随变化
最简单的做法是再声明一个变量circle,每次点击自增1,注意,左侧按钮也需要这个变量,因此要声明全局变量。
- 图片播放的同时,下面小圆圈模块跟随一起变化。
- 点击小圆圈,可以播放相应图片。
- 鼠标不经过轮播图,轮播图也会自动播放图片
- 添加一个定时器
- 自动播放轮播图,实际就类似于点击了右侧按钮
- 此时我们使用手动调用右侧按钮点击事件arrow_r.click()
- 鼠标经过,轮播图模块,自动播放停止。
- 节流阀
- 防止轮播图按钮连续点击造成播放过快。
- 节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。
- 核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
- 开始设置一个变量var flag = true;
- If(flag){flag = false} 关闭水龙头
- 利用回调函数动画执行完毕,flag=true 打开水龙头
- 返回顶部
- 滚动窗口至文档中的特定位置
- 语法:window.scroll(x,y)
- 参数x和y没有单位
- 筋斗云案例:
- 鼠标经过某个小li,筋斗云跟到当前小li位置
- 鼠标离开这个小li,筋斗云复原原来的位置
- 鼠标点击了某个小li,筋斗云就会留在点击这个小li的位置
- 利用动画函数做动画效果
- 原先筋斗云的起始位置是0
- 鼠标经过某个小li,把当前小li的offsetLeft位置作为目标值即可
- 鼠标离开某个小li,就把目标值设为0952
- 移动端网页特效
- 目标:
- 能够写出移动端触屏事件
- 能够写出常见的移动端特效
- 能够使用移动端开发插件开发移动端特效
- 能够使用移动端开发框架开发移动端特效
- 目标:
- 触屏事件:
- 移动端浏览器兼容性较好,我们不需要考虑以前JS的兼容性问题,可以放心的使用原生JS书写效果,但是移动端也有自己独特的地方。比如触屏事件touch(也称触摸事件),Android和IOS都有。
- touch对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或则触控板操作。
- 常见的触屏事件如下:
触屏touch事件 | 说明 |
touchstart | 手指触摸到一个DOM元素时触发 |
touchmove | 手指在一个DOM元素上滑动时触发 |
touchend | 手指从一个DOM元素上移开时触发 |
- 触摸事件对象(TouchEvent):
- Touchevent是一类描述手指在触摸平面(触摸屏,触摸板等)的状态变化的事件,这类事件用于描述一个或多个触点,使开发者可以检测触点的增加和减少,等等
- touchstart、touchmove、touchend三个事件都有各自事件对象
- 触摸事件对象重点我们看三个常见对象列表:
- 触摸事件对象(TouchEvent):
触摸列表 | 说明 |
touches | 正在触摸屏幕的所有手指的一个列表 |
targetTouches | 正在触摸当前DOM元素上的所有手指的一个列表 |
changedTouches | 手指状态发生了改变的列表,从无到有 或则 从有到无 |
- 如果侦听的是一个DOM元素,touches和targetTouches是一样的
- 当我们手指离开屏幕的时候,就没有了touches和targetTouches列表,但是会有changedTouches
- 因为我们一般都是触摸元素(给元素注册事件) 所以最经常使用的是targetTouches
- 移动端拖动元素
- touchstart、touchmove、touchend可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值 我们可以使用targetTouches[0]里面的pageX和pageY
- 移动端拖动的原理:手指移动中,计算出手指移动的距离,然后用盒子原来的位置+手指移动的距离
- 手指移动的距离:手指滑动中的位置减去 手指刚开始触摸的位置
- 拖动元素三部曲:
- 触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
- 离开手指touchend
- 注意:手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动e.preventDefault()
- 移动端常见特效
- 移动端轮播图
- 移动端轮播图功能和pc端基本一致
- 可以自动播放图片
- 自动播放功能
- 开启定时器
- 移动端移动,可以使用translate移动
- 想要图片优雅的移动,请添加过渡效果
- 自动滚动-无缝滚动
- 可以自动播放图片
- 移动端轮播图功能和pc端基本一致
- 移动端轮播图
注意:我们判断条件是要等到图片滚动完毕再去判断,就是过渡完成后判断
此时需要添加检测过渡完成事件transitionend
判断条件:如果索引号等于3说明走到最后一张图片,此时索引号要复原为0
此时图片,去掉过渡效果,然后移动
如果索引号小于0,说明是倒着走,索引号等于2
此时图片,去掉过渡效果,然后移动
小圆点跟随变化效果
把ol里面li带有current类名的选出来去掉类名remove
让当前索引号的小li加上current add
但是,是等看过渡结束之后变化,所以这个写到transtionend事件里面
- 手指可以拖动播放轮播图
- 手指滑动轮播图
- 本质就是ul跟随手指移动,简单来说就是移动端拖动元素
- 触摸元素touchstart:获取手指初始化坐标
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
- 手指可以拖动播放轮播图
- classList
- classList属性是HTML5新增的一个属性,返回元素的类名,但是ie10以上版本支持(伪数组形成存储)
- 语法:元素对象名.classList
- 该属性用于在元素中添加,移除及切换CSS类。有以下方法
- 添加类:
- element.classList.add(‘类名’);
- 是在元素对象后面追加类名不会覆盖以前的类名,类名前面不需要加小点
- element.classList.add(‘类名’);
- 移除类:
- element.classList.remove(‘类名’);
- 切换类:
- element.classList.toggle(‘类名’);
- 触发事件,如果元素有该类就删除,没有就添加
- element.classList.toggle(‘类名’);
- 添加类:
- classList属性是HTML5新增的一个属性,返回元素的类名,但是ie10以上版本支持(伪数组形成存储)
- 返回顶部
- 当页面滚动某个地方,就显示,否则隐藏
- 滚动某个地方显示
- 事件:scroll页面滚动事件
- 如果被卷去的头部(window.pageYOffset)大于某个数值
- 点击,window.scroll(0,0)返回顶部
- 当页面滚动某个地方,就显示,否则隐藏
- click延时解决方案
- 移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放(double tab to zoom)页面
- 解决方案:
- 方案一:禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300ms的点击延迟。
- <meta name="viewport" content="user-scalable=no">
- 方案二:利用touch事件自己封装这个事件解决300ms延迟。、
- 原理就是:
- 当我们手指触摸屏幕,记录当前触摸时间
- 当我们手指离开屏幕,用离开的时间减去触摸的时间
- 如果时间小于150ms,并且没有滑动过屏幕,那么我们就定义为点击
- 代码实现:
- 原理就是:
- 方案一:禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300ms的点击延迟。
//封装tap,解决click300ms延时
function tap(obj, callback) {
var isMove = false;
var startTime = 0; //记录触摸时候的时间变量
obj.addEventListener('touchstart', function (e) {
startTime = Date.now(); //记录触摸时间
})
obj.addEventListener('touchmove', function (e) {
isMove = true; //看看是否有滑动,有滑动算拖拽,不算点击
})
obj.addEventListener('touchend', function (e) {
if (!isMove && (Date.now() - startTime) < 150) {//如果手指触摸和离开时间小于150ms算点击
callback && callback();//执行回调函数
}
isMove = false //取反 重置
startTime = 0;
})
}
//调用
tap(div, function () {//执行代码})
- 方案三:使用插件。fastclick插件解决300ms延迟。
- 第一步,引入插件
- <script src='fastclick.js'></script>
- 第二步,在click监听事件之前写如下代码,后面的click事件就不会有延时问题了
- 第一步,引入插件
- 方案三:使用插件。fastclick插件解决300ms延迟。
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}
- 什么是插件
- 移动端要求的是快速开发,所以我们经常会借助于一些插件来帮我们完成操作,那么什么是插件呢?
- JS插件是js文件,它遵循一定规范编写,方便程序展示效果,拥有特定且方便调用。如轮播图和瀑布流插件。
- 特点:它一般是为了解决某个问题而专门存在,其功能单一,并且比较小
- fastclick插件解决300ms延迟,使用延时
- GitHub官网地址:https://github.com/ftlabs/fastclick
- Swipper插件的使用
- 中文官网地址:https://www.swiper.com.cn/
- 引入插件相关文件。
- 按照规定语法使用
- 中文官网地址:https://www.swiper.com.cn/
- 其他移动端常见插件:
- superslide:http://www.superslide2.com/
- iscroll:https://github.com/cubiq/iscroll
- 插件使用总结
- 确认插件实现的功能
- 去官网查看使用说明
- 下载插件
- 打开demo实例文件,查看需要引入的相关文件,并且引入
- 赋值demo实例文件中的结构html,样式css以及js代码
- 972
- 移动端视频插件zy.media.js
- H5给我们提供了video标签,但是浏览器的支持情况不同。
- 不同的视频格式文件,我们可以通过source解决。
- 但是外观样式,还有暂停,播放,全屏等功能我们只能自己写代码解决。
- 这个时候我们可以使用插件方式来制作。
- 移动端常用的开发框架:
- 框架概述
- 框架,顾名思义就是一套架构,它会基于自身的特点向用户提供一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
- 插件一般是为了解决某个问题而专门存在,其功能单一,并且比较小。
- 前端常用的框架有Bootstrap、vue、Angular、React等。既能开发PC端,也能开发移动端
- 前端常用的移动端插件有swiper、superslide、iscroll等。
- 框架概述
- 框架:大而全,一整套解决方案
- 插件:小而专一,某个功能的解决方案
- Bootstrap
- Bootstrap是一个简洁、直观、强悍的前端开发框架,它让web开发更迅速、简单。
- 它能开发PC端,也能开发移动端
- Bootstrap JS插件使用步骤:
- 引入相关js文件
- 复制HTML结构
- 修改对应样式
- 修改相应JS参数
- 本地存储:
- 目标:
- 能够写出sessionStorage数据的存储以及获取
- 能够写出localStorage数据的存储以及获取
- 能够说出它们两者的区别
- 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变得越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
- 目标:
- 本地存储特性
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage约5M、localStorage约20M
- 只能存储字符串,可以将对象JSON.stringify()编码后存储
- window.sessionStorage
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 存储数据:
- sessionStorage.setItem(key,value)
- 获取数据:
- sessionStorage.getItem(key)
- 删除数据:
- sessionStorage.removeItem(key)
- 删除所有数据:
- sessionStrorage.clear()
- 如何看数据:
- F12打开控制台
- 在上面菜单栏中选择“application”
- 在右侧storage下面选中“Session Storage”
- 双击下面文件即可看见存储的数据和值
- window.losalStorage
- 生命周期永久生效,除非手动删除,否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
- 存储数据:
- localStorage.setItem(key,value)
- 获取数据:
- localStorage.getItem(key)
- 删除数据:
- localStorage.removeItem(key)
- 删除所有数据:
- localStorage.clear()
- 记住用户名:
- 案例分析:
- 把数据存起来,用到本地存储
- 关闭页面,也可以显示用户名,所以用到localStorage
- 打开页面,先判断是否有这个用户名,如果有,就在表单里面显示用户名,并且勾选复选框
- 当复选框发生改变的时候change事件
- 如果勾选,就存储,否则就移除
- 代码实现:
- 案例分析:
<input type="text" id="uname">
<input type="checkbox" name="" id="remember">记住用户名
<script>
var uname = document.querySelector('#uname')
var remember = document.querySelector('#remember')
if (localStorage.getItem('uname')) {
uname.value = localStorage.getItem('uname')
remember.checked = true;
}
remember.addEventListener('change', function () {
if (this.checked) {
localStorage.setItem('uname', uname.value)
} else {
localStorage.removeItem('uname')
}
})
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?