上一篇:18.JS基础(四)
JavaScript学习
BOM
BOM:Browser Object Model 浏览器 对象 模型
- BOM提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window
- JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C
- BOM缺乏标准,BOM最初是Netscape浏览器标准的一部分
- 直到HTML5发布,W3C将 BOM 主要内容纳入了 HTML5 规范之中
- BOM是为了操作浏览器对象出现的API,window是其核心对象
原生对象与宿主对象
原生对象(本地对象):native object
- ECMA所定义的对象
- Number、String、Boolean、Object、Array、Function、Date、RegExp、内置对象(如 Math不需要实例化)、Error …
宿主对象:host object( 如 window、BOM、DOM )
- 什么是宿主?
- web的运行环境,即操作系统、浏览器
- 宿主提供的对象 -> 宿主对象
window对象
window对象是浏览器中的Global对象
window.open()
方法打开一个页面,返回一个新窗口
var newWindow = window.open(URL,name,specs)
URL:打开页面的URL,没有指定URL将打开新的空白窗口
name:_blank 新窗口打开,默认
_self 当前页面打开
......
specs:一个逗号分隔的项目列表。支持以下值:
width=pixels height=pixels
最小值为100
left=pixels top=pixels ......
示例 window.open('','_blank','left=200,top=100,width=400,height=200');
-
window.close() 方法用于关闭浏览器窗口(只能关闭新打开的窗口)
-
window.resizeTo(width,height) 调整窗口大小
-
window.resizeBy(width,height) 调整窗口大小
-
注:此功能在一些标签型浏览器中无效
-
window.scrollX 获取页面水平方向滚动的像素值
-
window.scrollY 获取页面垂直方向滚动的像素值
-
window.scrollTo(x,y) 方法可把页面内容滚动到指定的坐标
可以用来做固定窗口返回顶部操作
<botton id="btn">按钮</botton>
<script>
btn.onclick = function (){
window.scrollTo(0,0)//返回顶部
}
</script>
-
window.screenLeft 属性返回窗口相对于屏幕的X坐标
-
window.screenTop 属性返回窗口相对于屏幕的Y坐标
-
window.screenX 属性返回窗口相对于屏幕的X坐标
-
window.screenY 属性返回窗口相对于屏幕的Y坐标
-
window.setInterval ( 函数/名称 , 毫秒数 )
-
表示每经过一定的毫秒后,执行一次相应的函数(重复)
//每隔两秒执行一次回调函数(重复执行) var timer1 = setInterval(function (){ console.log( 12345 ) },2000) console.log( timer1 )//1 计时器编号 计时器ID
-
清除计时器:clearInterval(计时器编号/计时器ID)
clearInterval(timer1)
-
-
window.setTimeout ( 函数/名称 , 毫秒数 )
-
表示经过一定的毫秒后,只执行一次相应的函数(不重复)
// 两秒一行执行一次回调函数(不重复执行) var timer2 = setTimeout(function (){ console.log( 5678 ) },2000) console.log( timer2 )//2 计时器编号 计时器ID
-
清除计时器:clearTimeout( )
clearTimeout(timer2)
例题
#box{ width: 100px; height: 100px; position: absolute; left: 10px; top: 50px; background-color: red; }
<div id="box"></div> <button id="btn">按钮</button>
<script> btn.onclick = function (){ var num = 10 var timer = setInterval(function (){ num += 5 box.style.left = num + 'px' if (num >= 1000) { // 走到1000清楚计时器 clearInterval(timer) } },30); } </script>
-
-
提示框 alert (“ ”);
-
用户必须先关闭该消息框然后才能继续进行操作
alert('你傻吗?') // 警告弹窗
-
-
确认框 confirm(“ ”);
-
confirm(“需要确认的内容”);
-
选择“确定”返回true
-
选择“取消”返回false
var res = confirm('您输入的内容未保存,您确定要离开码?') // 确认弹窗
-
-
输入框 prompt(“ ”,“ ”);
-
prompt(“对话框的提示文本”,“默认的输入文本”);
-
单击取消,则返回 null;单击确认,则返回输入的文本
var res = prompt('请输入内容','') // 输入弹窗
-
history对象
history对象包含有关用户的访问历史记录
-
length 返回浏览器历史列表中的 URL 数量
-
forward() 加载 history 列表中的下一个 URL
-
back()
加载 history 列表中的上一个 URL -
go()
加载 history 列表中的某个具体页面-
history.go(-1) 后退一页
-
history.go(1) 前进一页
…
-
-
练习:
-
由页面a跳转到页面b,5秒后自动返回页面a,也可点击立即返回
//页面a <botton id="bot">点击</botton> <script> bot.onclick = function(){ location.href = "./72 历史记录跳转2.html" } </script>
//页面b <body> 你猜不猜啊 <botton id="but">点击</botton> <script> but.onclick = function(){ location.href(history.go(-1)) } var times = 5 ; var mm = setInterval(function(){ times -=1; console.log(times + "s后返回上一页") if(times <=0){ location.href(history.go(-1)) clearInterval(mm) } },1000) </script> </body>
-
location对象
location对象包含有关当前页面的URL信息
-
host 属性设置或返回主机名和当前 URL 的端口号
-
port 属性设置或返回当前 URL 的端口号
-
href 属性设置或返回完整的 URL ……
console.log( location.href )// 当前页面的URL地址location.href = './myblog.html' // 跳转到指定页面location.href = 'https://www.baidu.com/' // 跳转到指定页面
-
search 属性设置或返回URL查询字符串
console.log( location.search )
-
assign() 方法加载新的文档
-
reload()方法重新加载当前文档(刷新)
btn1.onclick = function(){ windon = location.reload() //慎用 }
-
replace() 方法用新的文档替换当前文档---->刷新
-
…
navigator对象
navigator对象用于提供与用户浏览器相关的信息
-
appCodeName 属性返回浏览器的代码名
-
appName 属性返回浏览器的名称
-
cookieEnabled 属性返回指明浏览器中是否启用cookie的布尔值
-
platform 属性返回运行浏览器的操作系统平台
-
appVersion 属性返回浏览器的平台和版本信息
-
userAgent 属性返回用户浏览器发送服务器的user-agent头部的值
识别浏览器
var str1=window.navigator.userAgent;
var str2=window.navigator.appVersion;
结合indexOf( )和toLowerCase( )方法可识别用户浏览器
screen对象
screen对象包含有关客户端显示屏幕的信息
- width 属性返回显示器屏幕的宽度
- height 属性返回显示器屏幕的高度
- availHeight 属性返回显示屏幕的高度 (除 Windows 任务栏之外)
- availWidth 属性返回显示屏幕的宽度 (除 Windows 任务栏之外)
- …
document对象
- document 对象是 Window 对象的一部分
- 可通过 window.document 属性对其进行访问
- 每个载入浏览器的 HTML 文档都会生成 document 对象
- document 对象与它所包含的各种节点构成了早期的文档对象模型(DOM 0级)
- document:包含整个 HTML 文档,可被用来访问文档内容及其所有页面元素
- …
DOM
- DOM:Document Object Model 文档 对象 模型
- DOM是针对HTML和XML文档的API
- DOM描绘了一个层次化的节点树,即HTML文档中的所有内容都是节点(node)
- DOM树中的所有节点均可通过JS进行访问,允许开发人员添加、移除、修改和查询页面的某一部分
节点类型
- 整个文档是一个文档节点
- 每个HTML元素是元素节点
- HTML元素内的文本是文本节点(回车也是文本节点)
- 每个HTML的属性是属性节点
- 注释是注释节点
获取元素节点
- document.getElementById(‘’); 单个元素
- document.getElementsByName(‘’); 元素集合(表单元素)
- document.getElementsByTagName(‘’); 元素集合
- document.getElementsByClassName(‘类名’); 元素集合
- document.querySelector(‘css选择器’); 单个元素
- document.querySelectorAll(‘css选择器’); 元素集合
- 元素集合的 length 属性表示集合中元素的个数
元素节点的值
- innerHTML 设置或返回元素标签内的所有内容(包含html)
- innerText 设置或返回元素标签内的所有内容(不包含html)
- value 设置或返回表单元素的值
- textContent 设置或返回指定节点的文本内容(IE678不支持)
元素节点的样式
- 元素节点都有一个style属性,style是一个样式对象,用于访问或设置css样式
- dom.style.属性 = 值;
- dom.style.cssText = ‘属性:值; 属性:值;’
- dom.className = ‘类名’
nodeType 属性
返回一个整数,这个数值代表节点的类型
- 元素节点 返回 1
- 属性节点 返回 2
- 文本节点 返回 3
- 注释节点 返回 8
- 文档节点 返回 9
nodeName 属性
返回节点的名称
- 元素节点的 nodeName 是标签名称 ( 大写 )
- 属性节点的 nodeName 是属性名称
- 文本节点的 nodeName 永远是 #text
- 注释节点的 nodeName 永远是 #comment
- 文档节点的 nodeName 永远是 #document
tagName 属性
返回元素节点的标签名
- 在 HTML 中,tagName 属性的返回值始终是大写的
nodeValue 属性
返回节点的值
- 对于元素节点,nodeValue 返回值是 undefined 或 null
- 对于文本节点,nodeValue 返回文本内容
- 对于属性节点,nodeValue 返回属性值
- 对于注释节点,nodeValue 返回注释内容
- 对于文档节点,nodeValue 返回 null
元素节点使用innerHTML、innerText、value取值
节点关系
- 节点之间的关系,通常用家庭中的辈分关系来描述
- 祖先 -> 父辈 -> 子女(兄弟姐妹) -> 子孙
-
parentNode:返回父节点
-
children:返回所有元素子节点
- IE678 可以获取到注释节点,在IE678这样获取的时候注意不要写注释
- childNodes:所有子节点 ,IE678与高版本浏览器返回值不一样
- 高版本浏览器返回文本节点(回车),IE678返回元素节点
- nextSibling:下一个兄弟节点
- previousSibling:上一个兄弟节点
- firstChild : 第一个子节点
- lastChild:最后一个子节点
- 高版本浏览器返回元素节点,IE678不支持
- nextElementSibling
- previousElementSibling
- firstElementChild
- lastElementChild
节点方法
案例:
<div class="box">
<p class="p1">好玩的游戏!</p>
<p>
用户名:<input type="text" value="oppo" class="p2">
</p>
<p>1</p>
<p>2</p>
<p>3</p>
<ul>
<li class="list1" haha="哈哈">list1</li>
<li class="list2">list2</li>
<li class="list3">list3</li>
</ul>
</div>
//在js中操作HTML,先声明
var ul = document.querySelector(".box ul")
-
createElement(“标签名”) 创建元素节点
var list = document.createElement("li")
-
createTextNode(“”) 创建文本节点
var txt=document.createTextNode('-list25-');
-
父元素调用
-
appendChild(node) : 末尾插入一个节点node
ul.appendChild(list)
-
insertBefore(newNode,target) : target之前插入节点node
ul.insertBefore(list,ul.children[2])
-
removeChild(node) : 移除某个子节点
ul.removeChild(ul.children[1])
-
replaceChild(newNode,oldNode) : newNode替换oldNode
ul.replaceChild(list,ul.children[2])
-
-
cloneNode(boolean) : 复制一个节点
-
true:深复制,复制节点及其整个子节点树
var list1 = ul.cloneNode(true)
-
false : 浅复制,只复制节点本身
var list2 = ul.cloneNode(false)
-
注:不会复制添加到DOM节点中的JS属性,例如事件处理程序等
-
-
getAttribute(“name”) 获取节点上name属性的值
//ul的第一个li元素上的自定义属性hehe console,log(ul.children[0].getAttribute("hehe")) //输出 呵呵
-
setAttribute(“name”,“value”) 设置节点上name属性的值为value
ul.children[0].setAttribute("haha",哈哈)//添加新属性与值 ul.children[0].setAttribute("hehe",呵呵)//修改原有属性的值
-
removeAttribute(“name”) 删除节点上的name属性
ul.children[0].removeAttribute("class")//删除自动属性 ul.children[0].removeAttribute("haha")//删除自定义的属性
-
getAttributeNode(“type”) 获取节点上type属性节点
console.log(ul.children[0].getAttributeNode("haha")) //输出:haha="哈哈"
-
dom.remove() 删除dom节点(IE不支持)
拓展:
-
dom对象自带属性,可以直接访问
console.log( boxs[0].id ) console.log( boxs[0].className ) console.log( boxs[0].title )
-
元素自定属性不能直接访问
console.log( boxs[0].hehe )// undefined console.log( boxs[0]['data-index'] )// undefined
-
html和body可以不获取直接用
document.documentElement == document.querySelector('html') document.body == document.querySelector('body')
-
documentFragment
-
documentFragment是一个文档碎片,是一种‘轻量级节点’,是一个虚拟的节点对象
-
documentFragment的nodeType值为11,nodeName的值为#document-fragment
-
通常作为仓库来使用,不存在DOM树上,将多个需要插入的新节点放在文档碎片上,再插入文档中可以优化DOM操作
-
虚拟的节点对象,包含节点的所有属性和方法
-
创建一个文档碎片(空容器)
var fragment = document.createDocumentFragment()
-
将新节点插入文档碎片
fragment.appendChild(newNode)
-
将文档碎片插入box节点中
box.appendChild(fragment)
例题:在ul中插入30个li
<ul class="ul"> <!--<li>商品1</li> <li>商品2</li> <li>商品3</li> --> </ul> <script> // 获取ul节点 var ul = document.querySelector(".ul"); //创建li元素节点 var list = document.createElement("li"); //给list新节点赋值 list.innertext = "商品X"; //创建一个文档碎片 var wap = document.createDocumentFragment(); //插30个,需要循坏 for(var i = 0;i < 30;i++){ //在最后一个li插入新的list节点 wap.appendChild(list) } </script>
获取元素样式
在js中元素的样式有两种:行间样式与非行间样式
// 1. 行间样式:
<div id="box1" style="width:300px; height:100px;"></div>
console.log(box1.style.width);
// 2. 非行间样式:
#box2 {width: 200px; height: 50px;}
<div id="box2"></div>
console.log(box2.style.width);
- getComputedStyle:获取样式(IE678除外)
- 如:getComputedStyle(dom对象,参数).样式
- 第一个参数是要获取样式的元素对象
- 第二个参数可以传递任何数据,通常为false或null或空
- currentStyle:IE678获取样式的方法
- 如:dom.currentStyle.样式
练习:
-
自己封装获取元素样式的函数(注意兼容问题)
// 如何解决兼容问题? // 获取元素样式(兼容IE678) function getStyle(dom,style){ if (dom.currentStyle) { // IE678 return dom.currentStyle[style] } else { // 非IE678 return getComputedStyle(dom)[style] } } console.log( getStyle(box1,'height') ) console.log( getStyle(box2,'height') )
offset/client系列属性
-
offsetLeft:获取对象左侧与定位父级之间的距离(默认是body)
-
offsetTop:获取对象上侧与定位父级之间的距离(默认是body)
-
offsetWidth:获取元素自身的宽度(包含边框和 padding)
-
offsetHeight:获取元素自身的高度(包含边框和 padding)
-
offsetParent:返回元素的定位父级
-
clientWidth:获取元素自身的宽度(不含边框)
-
clientHeight:获取元素自身的高度(不含边框)
-
clientLeft、clientTop:获取元素内容到边框的距离,效果和边框宽度相同,很少使用
-
document.body.offsetWidth body的宽度(包含边框)
-
document.body.offsetHeight body的高度(包含边框)
-
document.body.clientWidth body的宽度(不含边框)
-
document.body.clientHeight body的高度(不含边框)
-
document.documentElement.offsetWidth html文档的宽
-
document.documentElement.offsetHeight html文档高度
-
document.documentElement.clientWidth 浏览器可视区宽度(不含滚动条位置)
-
document.documentElement.clientHeight 浏览器可视区高度(不含滚动条位置)
其他
-
window.innerWidth 浏览器可视区宽度(含滚动条位置)
-
window.innerHeight 浏览器可视区高度(含滚动条位置)
-
document.documentElement.scrollWidth 网页正文全文宽,包括滚动条未见区域
-
document.documentElement.scrollHeight 网页正文全文高,包括滚动条未见区域
事件
- 事件指的是文档或者浏览器窗口中发生的一些特定交互瞬间
- 事件是可以被 JavaScript 侦测到的行为
- 事件可以提高网页的交互性
- 事件通常与函数配合使用,当事件发生时执行对应的函数
- 事件驱动(事件触发时,驱动函数执行)
常见的事件类型
-
blur 元素失去焦点,方法 blur()
user.onblur = function (){//失去焦点时触发 console.log( '失去焦点' ) }
-
focus 元素获得焦点,方法 focus()
user.onfocus = function (){//获得焦点时触发 console.log( '获得焦点' ) }
-
input 用户输入时触发
user.oninput = function (){// 用户输入时触发 console.log( '输入值' ) }
-
change 用户改变域的内容(值改变时触发)
user.onchange = function (){// 输入的值改变时触发 console.log( '值改变' ) }
-
###click 鼠标左键点击某个对象
document.onclick = function (){ console.log( '右击事件' ) }
-
dblclick 鼠标双击某个对象
documeny.ondblclick = function(){ console.log('双击事件') }
-
contextmenu 鼠标点击右
document.oncontextmenu = function (){ console.log( '右击事件' ) }
-
keydown 键盘某个键被按下(所有键)
document.onkeydown = function (){ console.log( '键盘按键按下' ) }
-
keypress 键盘某个键被按下(不包括系统功能键,如箭头键,ctrl,F1,F2等)
document.onkeydown = function (){ console.log( '键盘按键按下' ) }
-
keyup 键盘某个键被松开
document.onkeyup = function (){ console.log( '键盘按键抬起' ) }
-
mousedown 某个鼠标按键被按下
document.onmousedown = function (){ console.log( '鼠标按下' ) }
-
mousemove 鼠标在某元素上移动
document.onmousemove = function (){ console.log( '鼠标在某元素上移动' ) }
-
mouseup 某个鼠标按键被松开
document.onmouseup =function(){ console.log('鼠标松了') }
-
mouseenter 鼠标进入某元素
user.onmouseenter = function (){ console.log( '鼠标进入' ) }
-
mouseleave 鼠标从某元素移开
user.onmouseleave = function (){ console.log( '鼠标离开' ) }
-
mouseover 鼠标移到某元素之上(冒泡)
user.onmouseover = function (){ console.log( '鼠标进入' ) }
-
mouseout 鼠标从某元素移开(冒泡)
user.onmouseout = function (){ console.log( '鼠标离开' ) }
-
submit form提交时触发
这个事件是form表单的
// 当我们点击input登录时,触发的是form元素的submit事件 form.onsubmit = function (){ console.log( '表单提交' ) }
-
load 某个页面或图像被完成加载
var img = document.querySelector('img') //console.log( img.clientWidth )// 0 img.onload = function (){ console.log( '图片加载完成时触发' ) console.log( img.clientWidth )// 1200 }
-
…
事件模型
- 事件模型主要讲的是事件的注册、解除及事件的流向/执行顺序
- JavaScript中的两种事件模型:DOM 0级事件模型 和 DOM 2级事件模型
DOM 0级事件模型
-
DOM0级事件模型是早期的事件模型,所有的浏览器都支持
-
注册事件:在事件类型前面加on,如:
onclick
、onmouseover
… -
解除事件:dom.onclick = null
var remove = document.querySelector('.remove') remove.onclick = function (){ console.log( '移除事件' ) btn1.onclick = null // 移除btn的点击事件
-
在DOM 0级事件模型中,每个DOM对象只能注册一个相同类型的事件,注册多个则会发生覆盖,只执行最后一个
DOM2级事件模型
-
DOM2级事件模型是较新的事件模型,IE678不支持的
-
注册事件:
function fn2(){ console.log( 'btn2 2' ) } btn2.addEventListener('click',fn2,false)
addEventListener(type,fn,useCapture) 事件监听器
- type----事件类型,例:click、mouseover…
- fn----事件处理函数
- useCapture----布尔值,默认false
- ( true表示事件捕获,false表示事件冒泡 )
-
解除事件:
removeEventListener(type, fnName, useCapture)
remove.onclick = function (){ console.log( '移除事件' ) // btn1.onclick = null // 移除btn的点击事件 // btn2.removeEventListener('click',function (){ // console.log( 'btn2 2' ) // })// 不能移除事件,因为这里要移除的函数和添加事件的函数不是同一个 btn2.removeEventListener('click',fn2) }
-
每个DOM对象可以注册多个相同类型的事件,会依次执行,不会发生覆盖
-
IE678不支持addEventListener,但提供自己的实现方式:
-
注册事件:
attachEvent( type , fn )
- type----事件类型,例:onclick、onmouseover
- fn----事件处理函数
- 没有第三个参数
-
解除事件:
detachEvent( type , fnName )
练习:封装事件监听/移除函数(兼容IE678)?
function addEvent(){}
function removeEvent(){}
<button id="btn">点击</button>
<script>
btn.onclick = function(){
if(btn.addEventlistener){
btn.addEventlistener("click",function(){},false)
}else {
btn.attachEvent(onclick,function(){})
}
}
// 移除事件监听(兼容IE678)
function removeEvent(dom,type,fnName){
if (dom.detachEvent) {
// IE678
dom.detachEvent('on'+type,fnName);
} else {
// 非IE678
dom.removeEventListener(type,fnName,false);
}
}
触发事件
- 事件通常与函数结合使用,函数不会在事件触发前被执行
- BUT,我们也可以主动触发事件
// DOM 0级事件模型
btn.onclick = function(){
console.log("btn被点击1")
}
btn.onclick()// 触发事件
// DOM 2级事件模型
btn.addEventListener("click", function(){
console.log("btn被点击2")
})
// 创建一个事件对象
var e = new Event("click")
// 触发元素的一个事件
btn.dispatchEvent(e)
事件流
-
事件流:事件的流向,事件的执行顺序
-
子元素和父元素都定义了相同的事件,比如都定义了click事件,当点击子元素时,父元素的click事件也会被触发,JS里称这种事件连续发生的机制为
事件冒泡
或事件捕获
-
IE:事件从里向外发生,事件从最精确对象(target)开始触发,然后到最不精确的对象(document)触发,即
事件冒泡
-
网景:事件从外向里发生,事件从最不精确的对象(document)开始触发,然后到最精确对象(target)触发,即
事件捕获
-
W3C将两者进行中和,在标准W3C的事件模型中,事件先进入捕获阶段,再进入冒泡阶段
不管是事件冒泡,还是事件捕获,都有 '传播' 的特征!!
事件对象
- 当事件触发时,事件处理函数将被执行
- 在事件处理函数中,可以获取到一个与事件相关的对象,即事件对象(event对象)
- event对象中包含了所有与事件相关的信息,如:
- 获取键盘按下的按键码
- 获取鼠标的位置坐标
- 获取事件名称
- 获取事件生成的时间
- 获取事件的类型
- 等等…
获取event对象
- 所有浏览器都支持event对象,只是支持的方式不一样
- FireFox、Chrome等浏览器要获取到event对象,需要从函数中传入,参数名随意
- 而IE在浏览器中event作为window对象的一个属性存在,可以直接使用 event
// 例如:
document.onmousedown=function ( e ){
var ev = e || window.event //兼容各个浏览器
console.log(ev)
}
// 注意 var ev = e || event 顺序!
常用的属性方法
-
clientX/clientY
返回当事件被触发时,鼠标指针的坐标(到浏览器窗口的坐标) -
offsetX/offsetY
返回当事件被触发时,鼠标指针的坐标(在事件源中的坐标) IE -
pageX/pageY
返回当事件被触发时,鼠标指针的坐标(整个页面中的坐标) 火狐 -
button
返回触发事件的鼠标按键 -
which
返回触发事件的按键码(针对键盘和鼠标事件) 火狐 -
keyCode
返回键盘按键的按键码(ASCII码) IE -
组合键:
ctrlKey、altKey、shiftKey、metaKey
-
触发事件的元素,叫事件目标(事件源)
属性
event.target
指向事件目标 -
在IE中使用:
event.srcElement
指向事件目标兼容写法
target = event.target || event.srcElement
-
event.relatedTarget 获取触发事件的目标源,与target相反
-
event.fromElement IE获取触发事件的目标源,与srcElement相反
-
在mouseover事件中
,它指向鼠标来自哪个元素 -
兼容写法
from = event.relatedTarget || event.fromElement
-
event.relatedTarget 获取触发事件的目标源,与target相反
-
event.toElement IE获取触发事件的目标源,与srcElement相反
-
在mouseout事件中
,它指向鼠标去往的那个元素 -
兼容写法
to = event.relatedTarget || event.toElement
-
阻止默认行为
-
标准:event.preventDefault()
-
IE:event.returnValue = false
-
兼容写法
event.preventDefault ? event.preventDefault() : (event.returnValue = false)
-
也可以在函数中使用
return false
来阻止默认行为 -
阻止事件传播
-
标准:event.stopPropagation()
-
IE:event.cancelBubble = true
-
兼容写法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true)
事件委托
- 什么是事件:通俗讲click,mouseenter,mouseleave等就是事件
- 什么是委托:一个事件本来是加在某些元素上的,而你却加到其他元素上来完成这个事件
事件委托
就是事件目标自身不处理事件,而是把处理事件委托给其父辈元素来完成- 子元素把事件委托给父辈元素来完成
原理:利用事件传播的特征
-
事件委托的优点:
-
提高性能和效率
-
减少事件注册,节省内存占用
-
未来元素无需再次注册事件
-
…
document.body.onclick = function (ev){ // console.log( 'body被点击' ) var e = ev || window.event // 判断哪些是你想要的点击行为 // console.log( this )// body // console.log( e.target )// 点击谁就指向谁 if (e.target.tagName === 'BUTTON'&&e.target.className === 'add') { // var newLi = document.createElement('li') // newLi.innerText = '新的li' // list.appendChild(newLi) list.innerHTML += "<li> li X</>" } if (e.target.tagName === 'LI'&&e.target.parentNode.className === 'list') { e.target.style.backgroundColor = 'blue' } }
-
鼠标滚轮事件
需求:在box上滚动鼠标滚轮时,放大(前推)或缩小(后拉)box
// 获取用户浏览器相关的信息并转成小写字母
var userAgent = navigator.userAgent.toLowerCase()
// 把火狐浏览器判断出来
if (userAgent.indexOf('firefox')!==-1) {
// 是火狐浏览器
box.addEventListener('DOMMouseScroll',function (e){
// console.log( e )
// console.log( e.detail )// 前推 -4 后拉 4
if (e.detail < 0) {
// 前推 放大box
box.style.width = box.clientWidth+20+'px'
box.style.height = box.clientHeight+20+'px'
} else {
// 后拉 缩小box
box.style.width = box.clientWidth-20+'px'
box.style.height = box.clientHeight-20+'px'
}
})
} else {
// 非火狐浏览器
box.onmousewheel = function (ev){
// console.log( '鼠标滚轮事件' )
var e = ev || window.event
// console.log( e )
// console.log( e.wheelDelta )// 前推 120 后拉-120
if (e.wheelDelta > 0) {
// 前推 放大box
box.style.width = box.clientWidth+20+'px'
box.style.height = box.clientHeight+20+'px'
} else {
// 后拉 缩小box
box.style.width = box.clientWidth-20+'px'
box.style.height = box.clientHeight-20+'px'
}
}
}
scroll 滚动条
- scrollLeft:设置或获取当前左滚的距离,即左卷的距离
- scrollTop:设置或获取当前上滚的距离,即上卷的距离
- scrollHeight:获取对象可滚动的总高度
- scrollWidth:获取对象可滚动的总宽度
-
获取页面的滚动条:
var pageScroll = document.body.scrollTop //谷歌(低版本) var pageScroll = document.documentElement.scrollTop //火狐 IE
-
onscroll 事件,元素滚动条在滚动时触发
Math 对象
- Math 对象用于执行数学任务
- Math是一个内置对象,不需要创建,可以直接使用
Math对象常用API:
- Math.PI --------------返回圆周率3.1415926…
- Math.ceil(x) ----------对数值x进行向上取整
- Math.floor(x) --------对数值x进行向下取整
- Math.round(x) -------对数值x进行四舍五入取整
- Math.abs(x) ----------返回x的绝对值
- Math.pow(x,y) --------返回x的y次方
- Math.sqrt(x) ----------返回x的平方根
- Math.min(a,b,c…) ----返回abc…中的最小值
- Math.max(a,b,c…) ----返回abc…中的最大值
- Math.random() --------返回介于[0,1)之间的随机数
注意:Math.random() 理论上能得到0,实际使用几乎不可能得到0
-
如何得到 0 ~ 1 的随机整数[0,1]?
-
如何得到 0 ~ 5 的随机整数[0,5]?
-
如何得到 5 ~ 10 的随机整数[5,10]?
-
如何得到 8 ~ 24 的随机整数[8,24]?
-
写一个函数 randomInt(min,max) 随机生成[min,max]区间的整数?
三角函数
- Math.sin(x) ----- 返回x的正弦
- Math.cos(x) ----- 返回x的余弦
- … …
sinα = a/c
cosα = b/c
x 是弧度 - 一个角,可以用度数来表示,也可以用弧度来表示
- 弧度更加符合计算机的计算模式
- 【60°=π / 3】,【90°=π / 2】,【180°=π】,【360°=2π】
- 弧度 = 角度 × π / 180
怎么应用到代码里面?
- var angle = 60; //60度角
- var radian = angle * Math.PI / 180; //计算出弧度
案例:图形和动画:在编写动画或者游戏的时候,可能需要用到三角函数来计算旋转、移动路径等。例如,创建一个围绕某点旋转的动画,可以用三角函数计算各个时间点的 x,y 坐标。
let angle = 0;
let centerX = 100; // 圆心x坐标
let centerY = 100; // 圆心y坐标
let radius = 50; // 半径
setInterval(function () {
let x = centerX + radius * Math.cos(angle);
let y = centerY + radius * Math.sin(angle);
angle += 0.01;
// 然后在画布的 (x, y) 处绘制图像
}, 100);
物理模拟:在做物理模拟时,常常需要利用到三角函数。例如,做一个投射运动的模拟,当知道初速度和投射角度时,可以使用三角函数计算在不同的时间点物体的位置。
// 初始位置
let x = 0;
let y = 0;
// 初始速度
let v = 10;
// 抛射的角度,假设为45度
let angle = 45;
// 速度的x与y分量
let vx = v * Math.cos(angle * Math.PI / 180);
let vy = v * Math.sin(angle * Math.PI / 180);
// 重力加速度
let g = 9.8;
// 时间间隔
let dt = 0.1;
// 运动过程
for (let t = 0; t <= 2 * vy / g; t += dt) {
// 时间 t 时的位置
x = vx * t;
y = vy * t - 1/2 * g * t * t;
console.log("时间: " + t.toFixed(2) + " sec, 位置: (" + x.toFixed(2) + ", " + y.toFixed(2) + ")");
}
/**
这个程序模拟了一个物体以10m/s的速度,45度角抛出,并打印出每个时间t的位置。
注意这里我们假设了物体是在无阻力的情况下运动的,实际情况下可能需要考虑空气阻力等因素,计算会复杂一些。
此外,也请注意 JavaScript 中的 Math.sin 和 Math.cos 函数接收的参数是以弧度为单位的,
所以我们需要将角度转换为弧度,即:角度 * π / 180
*/
计算两点间距离和角度:这是一个经常遇到的问题,例如在地图应用中。当我们知道两点在地球上的经纬度后,可以使用三角函数来计算这两点之间的距离或者方向角。
在二维平面上,计算两点间的距离和角度的公式如下:
距离公式: d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 距离公式:d=\sqrt{(x_2 - x_1)^2+(y_2 - y_1)^2} 距离公式:d=(x2−x1)2+(y2−y1)2
角度公式: α = arctan ( ( y 2 − y 1 ) / ( x 2 − x 1 ) ) 角度公式:\alpha = \operatorname{arctan}((y_2-y_1)/(x_2-x_1)) 角度公式:α=arctan((y2−y1)/(x2−x1))
下面是使用这两个公式的JavaScript代码示例:
function calculateDistanceAndAngle(x1, y1, x2, y2) {
// 计算距离
let dx = x2 - x1;
let dy = y2 - y1;
let distance = Math.sqrt(dx*dx + dy*dy);
// 计算角度
// 注意:在javascript中,Math.atan的结果范围是-pi/2到pi/2
// 这意味着你可能需要根据dx和dy的符号调整角度
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
return {
distance: distance,
angle: angle
};
}
let point1 = {x: 0, y: 0};
let point2 = {x: 1, y: 1};
let result = calculateDistanceAndAngle(point1.x, point1.y, point2.x, point2.y);
console.log("Distance: " + result.distance);
console.log("Angle: " + result.angle);
/**
注意在这个示例中,我们用 Math.atan2(dy, dx) 函数而不是 Math.atan(dy/dx) 函数来计算角度,
因为 Math.atan2 能够正确处理 dx = 0 的情况,并且给出完整的 -π 到 π 范围的角度。
*/
- 练习:
- 随机生成[min,max]区间的整数
- 随机生成十六进制颜色字符串
- 随机生成四位验证码(字母数字组合)
Date 对象
- Date 对象用于处理日期与时间
- Date 对象自动使用当前系统的日期和时间作为其初始值
创建Date对象:
var d = new Date()
console.log(d)
// Tue Apr 30 2019 00:45:42 GMT+0800 (中国标准时间)
UTC
国际标准时间又称世界时
,以零经度线上的时间作为国际上统一采用的标准时间- 因为零经度线通过英国格林尼治天文台,所以国际标准时间也称为格林尼治时间GMT
- 国际标准时间的起点:1970/01/01 00:00:00
- 北京时区的时间起点:1970/01/01 08:00:00
- 所以,北京时间 = 国际标准时间 + 8小时
获取日期时间:
var d = new Date()
- getFullYear()------从 Date 对象以四位数字返回年份
console.log( d.getFullYear() ) //2021
- getMonth()---------从 Date 对象返回月份 (0 ~ 11)
console.log( d.getMonth() ) //5
- getDate()----------从 Date 对象返回一个月中的某一天 (1 ~ 31)
console.log( d.getDate() )//1
- getHours()---------返回 Date 对象的小时 (0 ~ 23)
console.log( d.getHours() )//18
- getMinutes()-------返回 Date 对象的分钟 (0 ~ 59)
console.log( d.getMinutes() )//21
- getSeconds()-------返回 Date 对象的秒数 (0 ~ 59)
console.log( d.getSeconds() ) //34
- getMilliseconds()–返回 Date 对象的毫秒(0 ~ 999)
console.log( d.getMilliseconds() )
- getDay()-----------从 Date 对象返回一周中的某一天 (0 ~ 6)
console.log( d.getDay() ) //6
- getTime()----------返回1970年1月1日至今的毫秒数
console.log( d.getTime() ) //1622510823157
- Date.now()--------返回当前时间与起始时间之间的毫秒数
console.log( d.Date.now() ) //1622510823157
11.返回转换后的Date对象与起始时间之间的毫秒数:
Date.parse('2019/05/01 00:00:00'); // 1556640000000
12.返回一个’年月日 时分秒’的本地格式字符串:
d.toLocaleString(); // '2021/4/30 上午12:55:42'
13.返回一个’年月日’的本地格式字符串:
d.toLocale<font color=red>Date</font>String(); // '2021/4/30'
设置日期时间:
var d = new Date()
-
setFullYear()------设置 Date 对象中的年份(四位数字)
d.setFullYear(2022)
-
setMonth()---------设置 Date 对象中月份 (0 ~ 11)
d.setMonth(5)// 设置月份 0-11 12->下一年的1月
-
setDate()----------设置 Date 对象中月的某一天 (1 ~ 31)
d.setDate(20)// 设置日期
-
setHours()---------设置 Date 对象中的小时 (0 ~ 23)
d.setHours(12)// 设置小时数
-
setMinutes()-------设置 Date 对象中的分钟 (0 ~ 59)
d.setMinutes(50)// 设置分钟数
-
setSeconds()-------设置 Date 对象中的秒钟 (0 ~ 59)
d.setSeconds(50)// 设置秒数
-
setMilliseconds()–设置 Date 对象中的毫秒 (0 ~ 999)
d.setMilliseconds(999)// 设置毫秒数
-
setTime()----------设置 Date 对象(向1970/1/1添加毫秒数)
d.setTime(1000*60*60*24)// 向1970.1.1时间累加一天的毫秒数 1970.1.2 08:00:00
创建指定时间点的Date对象
var d1 = new Date(毫秒数); //从时间起点开始叠加的毫秒数
var d2 = new Date('yyyy/MM/dd HH:mm:ss');
// Aug 20 2020 00:00:00 GMT+0800
var d = new Date('8/20/2020');
// Aug 20 2020 00:00:00 GMT+0800
var d = new Date('2020/8/20');
// Aug 20 2020 20:20:20 GMT+0800
var d = new Date('2020/8/20 20:20:20');
// Jan 20 2021 00:00:00 GMT+0800
var d = new Date(2020,12,20); // 年月日 月0-11 12下一年的一月
时区计算
var d = new Date();
// 0时区和当前时区的时间差,单位是分钟
var offset = d.getTimezoneOffset();
console.log( offset ); // -480 = 0时区时间-当前时区时间
var timezone = -offset / 60;
if (timezone > 0) {
console.log( '东' + timezone + '区' );
} else if (timezone < 0){
console.log( '西' + -timezone + '区' );
} else {
console.log( '零时区' );
}
操作世界时,在get或set后面加UTC,如 d.getUTCHours()、d.setUTCHours()
练习拓展
1.显示本地时间并数字为两位数
<h1>北京时间:2021年06月01日 10:05:35</h1>
setInterval(function (){
var d = new Date() // 创建日期对象
var year = d.getFullYear()
var month = d.getMonth()+1 // 0-11
var day = d.getDate()
var hour = d.getHours()
var minute = d.getMinutes()
var second = d.getSeconds()
month = month < 10 ? '0'+month : month
day = day < 10 ? '0'+day : day
hour = hour < 10 ? '0'+hour : hour
minute = minute < 10 ? '0'+minute : minute
second = second < 10 ? '0'+second : second
document.querySelector('h1').innerText = '北京时间:'+year+'年'+month+'月'+day+'日'+' '+hour+':'+minute+':'+second
},1000)
2.封装一个方法,返回中文的星期几
function getWeek(){
var d = new Date()
var num = d.getDay()// 0-6 0->星期日
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
return arr[num]
}
console.log( getWeek() ) // '星期二'
3. 2021年国庆倒计时
setInterval(function (){
// 2021年国庆倒计时
var d1 = new Date()// 现在的日期对象
var d2 = new Date('2021/10/1 00:00:00')// 未来的日期对象
var times1 = d1.getTime()// 1970.1.1到现在的总毫秒数
var times2 = d2.getTime()// 1970.1.1到2021.10.1的总毫秒数
var allTime = times2 - times1// 现在到2021.10.1的总毫秒数
// 思路1:用总的时间allTime分别计算出天数小时数分钟数。。。
// var days = parseInt( allTime / (1000*60*60*24) )
// var hours = parseInt( (allTime % (1000*60*60*24)) / (1000*60*60) )
// ...
// 思路2:计算出天数,利用时间互补性
var days = parseInt( allTime / (1000*60*60*24) )
var hours = 23 - d1.getHours()
var minutes = 59 - d1.getMinutes()
var seconds = 59 - d1.getSeconds()
var milliSeconds = 999 - d1.getMilliseconds()
document.querySelector('h1').innerText = '距离2021国庆节还有:'+days+'天'+hours+'时'+minutes+'分'+seconds+'秒'+milliSeconds
},1)
运动
运动原理:使用计时器,持续改变元素的属性
运动速度:取决于每次所走距离的多少
运动停止:判断什么时候到达目标位置,并清除计时器
匀速运动
运动频率和运动速度保持不变!
运动频率:计时器时间
运动速度:每次改变的量
// 关键步骤:
// 1. 获取当前值
var current = parseInt( getComputedStyle(dom)[attr] )
// 2. 判断运动方向
if (target > current){
speed = Math.abs(speed); // 向右运动
} else {
speed = -Math.abs(speed); // 向左运动
}
// 3. 到达目标位置:剩余运动量 <= 每次的运动量
if ( Math.abs(target-current) <= Math.abs(speed) ) {
...
} else {
...
}
缓冲运动
运动速度发生变化,由快到慢
// 缓冲运动的关键:
// 1. 获取当前值
var current = parseInt( getComputedStyle(dom)[attr] )
// 2. 频率不变,速度逐渐变慢
var speed = (target - current) / 10
// 3. 对速度取整,避免数据丢失
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed)
// 4. 到达目标位置:剩余运动量 <= 每次的运动量
if ( Math.abs(target-current) <= Math.abs(speed) ) {
...
} else {
...
}
透明度运动
透明度变量:var opa = 30
其他浏览器:dom.style.opacity = opa/100
IE浏览器:dom.style.filter = 'alpha(opacity:' + opa + ')'
注意:多元素进行相同的运动,属性都不能共用!
ES5 新增特性
严格模式
除了正常运行模式,ECMAscript5添加了第二种运行模式:“严格模式”(strict mode)。
顾名思义,这种模式使得Javascript在更严格的条件下运行。
设立"严格模式"的目的,主要有以下几个:
消除JavaScript语法的一些不合理、不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的JavaScript做好铺垫。
进入"严格模式"的标志:“use strict”;
将 “use strict”; 放在脚本文件的第一行,则整个脚本都将以"严格模式"运行。
<script>
"use strict";
console.log("全局严格模式。");
</script>
将"use strict"放在函数体的第一行,则整个函数以"严格模式"运行。
function strict(){
"use strict";
console.log("局部严格模式。");
}
ES5严格模式的限制规范:
1.变量声明必须使用var,否则报错
2.对不合理的操作显示报错,不再做静默失败处理
NaN = 123;
var abc = 'a12';
delete abc;
abc.length = 5;
3.禁止对象属性重名(IE)
4.禁止函数参数重名
5.禁止使用以0开头的八进制数字
ES6新的语法标准,八进制以0o来表示,与16进制的0x形成统一的语法格式
6.禁止使用with语句
7.强制为eval创建新作用域
eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。
如果参数是一个表达式,eval() 函数将执行表达式。
如果参数是Javascript语句,eval()将执行 Javascript 语句。
严格模式为JavaScript程序创建了第三种作用域:eval作用域
8.arguments不再追踪参数变化
var x = 1
function fn1(x) {
x = 2;
arguments[0] = 3;
alert(x);
}
fn1(4);
9.禁止使用arguments.callee
// 在匿名的递归函数中
var factorialArray = [1, 2, 3, 4, 5].map(function(n) {
return (n < 2) ? 1 : arguments.callee(n - 1) * n;
});
console.log(factorialArray);
10.函数中禁止this指向全局对象window,this变成undefined
11.函数必须声明在整个脚本或函数层面
12.新增一些保留字,不能使用他们作为标识符命名
implements, interface, let, package, private, protected, public, static, yield
下一篇:20.JS高级(一)
🌸友情推荐:全栈大佬笔记 Android领域肥宅