DOM
文档document对象模型
111获取元素的方式
html,head,body非常规
直接获取的就是整个html文档页面最外层的dom节点(基于js动态计算rem)
console.log(document.documentElement)
获取头部
console.log(document.head)
获取body
console.log(document.body)
常规
1.getElementById()
在文档中,获取一个元素来自id(括号里写id名)
标准方法,没有兼容性问题
console.log(document.getElementById())
变量法
<div id="box">33333
<ul>
<li>222</li>
<li>222</li>
<li>222</li>
</ul>
</div>
<ul>
<li>222</li>
<li>222</li>
<li>222</li>
</ul>
<script>
//获取box
//这个只能改变box里文字,如果box里套了ul,则ul会被省略掉(不知为什么)
var obox=document.getElementById("box")
obox.innerHTML="11111"
</script>
2.getElementsByClassName(伪数组)
<div id="box">33333
</div>
<ul>
<li class="newsitem">222</li>
<li class="newsitem">222</li>
<li class="newsitem">222</li>
</ul>
<script>
var items =document.getElementsByClassName("newsitem")
//是个伪数组,在控制台只是看着像数组,但是无法给数组附上数字的常用方法
//但是特殊的:它有length这个属性。意思就是它可以当作一个对象来看
//newsitem.innerHTML="123" 无效
//但是这个可以按数组形式写,强制改变第一个索引内容
items[0].innerHTML ="1234"
</script>
但是如果你就是想把这个伪数组变成真数组,需要借助一个新变量,然后Array.from(伪数组)转成真的
这时候newitems就可以加数组的方法了
var newitems=Array.from(items)
console,log(newitems)
3.getElementsByTagName可直接对标签设置(伪数组)
var items =document.getElementsByTagName("li")
console.log(items)
4.getElementsByName(伪数组)
<input type="text" name="username">
<button>111</button>
<script>
var item=document.getElementsByName("username")
console.log(item[0])
item[0].value="kerwin"//初始text
</script>
呈现效果(会自动给它一个初始text)
当然也可以直接给input设置value值
<input type="text" value="kerwin">
特殊的
(“”)写css选择器格式(id前记得写#)
5.querySelector(有兼容性问题可能)
只会返回一个对象,如果有多个,只能返回遇到的第一个
6.querySelectorAll(有兼容问题)
可以返回遇到的所有
222操作元素属性
分为 元素自带(原始)属性 ; 自定义属性
一.操作原生属性
.innerHTML = ""改内容
.type = ""改属性
.src = ""
.........
二.操作自定义属性
不能直接给你的box这样设置tiechui的属性box.teichui = "22222"
应该
1.setAttribute 设置/修改
2.getAttribute 获取
3.removeAttribute 删除
用法例如:
box.setAttribute("tiechui","2222")
console.log(box.getAttribute("tiechui"))
box.removeAttribute("tiechui")
4.还有一种h5新增的加自定义属性的方法 data-或dataset
写法1. data-
在html里写
获取方法(给出的是一个对象)
写法2. dataset
直接在js里写,让它加在html上
删除的话直接
密码可视案例
购物车全选案例
<input type="checkbox" id="allin">全选/全不选
<hr />
<ul class="shop">
<li><input type="checkbox">city lights版</li>
<li><input type="checkbox">candy版</li>
<li><input type="checkbox">Bambi版</li>
<li><input type="checkbox">cherry版</li>
</ul>
<script>
var Oallin = document.querySelector("#allin")
var Oitems = document.querySelectorAll(".shop input")
//找input,而不是找li
Oallin.onclick = function () {
//console.log(Oallin.checked)
//记得加.checked(说明获取了这个全选的checked)
for (var i = 0; i < Oitems.length; i++) {
Oitems[i].checked = Oallin.checked
}
}
for(var i=0;i<Oitems.length;i++){
Oitems[i].onclick=handler
}
//handler.function 写法错误
function handler(){
var count=0
for(var i=0;i<Oitems.length;i++){
if(Oitems[i].checked){
count++
}
if(count==Oitems.length){
Oallin.checked=true
}else{
Oallin.checked=false
}
}
}
</script>
333操作元素文本内容
当你获取完节点后,你需要往你的节点里放上文本或者标签
id.innerHTML
会得到整个部分
.innerText
只会得到文本信息,不解析html(也就是不会解析html里的标签)
.value
只适用于表单标签(像input之类的)
.value前不能写div的名字
渲染页面案例
444操作元素样式
1.获取行内样式的方法:style(可读可写)
1..style后面加的属性必须是你设置过的
console.log(box.style.width)
2. 如果这个属性有中间的连接符,就不能直接写在.style之后了,需要给它括上一个[“”]或者写成去掉连接符的驼峰式
console.log(box.style.["background-color"])
console.log(box.style.backgroundColor)
3. 还可以对你的css属性进行设置(可写)
直接赋值box.style.width = "200px",记得加引号
2.获取行内/内部/外部样式的方法:getComputedStyle(只可读,不能赋值写样式)
TIP:标准方法,有兼容性可能
(如果真的是低版本ie,就用obox.currentStyle.backgroundColor)
var obox=document.getElementById("box")//先获取这个节点
var res=getComputedStyle(obox)//这里不需要加引号,是一个函数
console.log(res)
//如果想拿到他的样式,直接在这个后面.属性就可以
var res=getComputedStyle(box).height
555操作元素类名
我们的目的是实现这样的效果:高亮功能
而上面刚讲的那个方法只能单独设置某一个样式,如果我们的需求很多需要批量设置上面的就不再合适
TIP:这样可以既设置css,也设置js
<div id="box" class="item item2 item3"></div>
.className(可读可写)
但是这个属性没有甄别能力,不会自动去重
读:console.log(box.className)就可以读到你html里的box的id
写(暴力修改删除增加):box.className = "item item2" 这样直接给它重新赋值,就相当于把之前的item3删掉了
classList 得到的东西是数组
//读
console.log(box.classList)
//增加。(但是如果不小心写重了,这个可以自动去重)
box.classList.add("")
//删除(只能一个一个删)
box.classList.remove("")
//切换 toggle (如果原来有就删掉,如果原来没有就加上)
box.classList.toggle("")
选项卡案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="a选项卡.css">
______________________________________________
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.header{
display: flex;
width: 500px;
}
.header li{
flex:1;
height: 50px;
line-height: 50px;
text-align: center;
flex:1 ;
border: 1px solid black;
}
.box{
position: relative;
}
.box li{
position: absolute;
left: 0;
top: 0;
width: 400px;
height: 200px;
background-color:antiquewhite;
padding: 50px;
display: none;
}
.header .active{
background-color:aquamarine;
}
.box .active{
display: block;
}
</style>
</head>
_________________________________________________
<body>
<ul class="header">
<!-- 给第一个设置active让它高亮 -->
<li class="active">英雄联盟</li>
<li>DOTA</li>
<li>风暴英雄</li>
<li>300英雄</li>
</ul>
<ul class="box">
<li class="active">《英雄联盟》(League of Legends,简称LOL)是由美国拳头游戏(Riot Games)开发、中国内地由腾讯游戏代理运营的英雄对战MOBA竞技网游。游戏里拥有数百个个性英雄,并拥有排位系统、符文系统等特色系统。
</li>
<li>222</li>
<li>《风暴英雄》 是由暴雪娱乐公司开发的一款运行在Windows和Mac OS上的在线多人竞技PC游戏。
游戏中的英雄角色主要来自于暴雪四大经典游戏系列:《魔兽世界》、《暗黑破坏神》、《星际争霸》和《守望先锋》。它是一款道具收费的游戏,与《星际争霸Ⅱ》基于同一引擎开发。</li>
<li><a href="https://300.jumpw.com/">300英雄</a></li>
</ul>
_______________________________________________________________
<script>
//获取
var oHeaderItems = document.querySelectorAll(".header li")
var oBoxItems = document.querySelectorAll(".box li")
//给这个oHeaderItems部分里的每一个li(也就是这里的i)绑定onclick的事件
for(var i=0;i<oHeaderItems.length;i++){
//这里需要注意的是"循环绑"的循环会瞬间执行完,所以你打印i的时候,并不能得到每个i事件的数字
//所以也就不能确定你点到的是哪一个
//自定义属性data-index(会被加在每个li中)(让它不去获取i了,而是去获取自身属性)
//为什么要这样,因为在你还没点之前,它就已经循环完了,所以你打印了只能显示个4
oHeaderItems[i].dataset.index = i
oHeaderItems[i].onclick = handler
}
//为了方便,易看,我们可以把上面onclick后的function单独在下面写(拆分)
function handler(){
console.log(this.dataset.index) //表示当前所点击的对象,可以在点击时得到相应的li
var index = this.dataset.index
for(var m=0;m<oHeaderItems.length;m++){
//思路:先把他们的active全部删掉,再在每次点击的时候单独加上
oHeaderItems[m].classList.remove("active")
oBoxItems[m].classList.remove("active")
}
//这里再单独加上
oHeaderItems[index].classList.add("active")
oBoxItems[index].classList.add("active")
}
</script>
</body>
</html>
666DOM节点
分类:元素/文本/属性/注释节点
(“”)
attribute[0/1/...]全部(属性节点)
| DOM节点 | |
|---|---|
| document | 根节点 |
| html | 根元素节点 |
| head/body/div/ul/... | 元素节点(可能是父元素也可能是子元素) |
| 文本内容(切记:包括换行和空格) | 文本节点 |
| 元素属性(type...) | 属性节点 |
| 注释内容 | 注释节点 |
获取节点的方法
childNodes属性(所有孩子节点)
vs
children(所有元素节点)
firstChild(第一个孩子节点)
vs
firstElementChild(第一个孩子元素节点)
lastChild(最后一个孩子节点)
vs
lastElementChild(最后一个孩子元素节点)
找上一个兄弟(哥哥节点)
previousSibling
vs
previousElementSibling
下一个(弟弟)
nextSibling
vs
nextElementSibling
这个区别不大
parentNode
vs
parentElement
操作DOM节点
创建一个节点
1. createElement:创建一个元素节点
var odiv=document.createElement(`div`)
//创建出来的就是一个可以使用的div元素
//往里面放东西的话就是
odiv.innerHTML=""
但是写到这里,这个div仍是无家可归,我们需要让它插到某个地方。
//(括号里都是对象,不是id)
//给box追加一个孩子(插入节点,追加)
box.appenChild(odiv)
//在某个之前插入(要插入的节点,在谁前面插入)
box.insertBefore(odiv,child)
可以给它正常加样式
2.删除节点
//(括号里都是对象,不是id)
//删除节点(括号里是对象)
box.removeChild(child)
//删除自己以及后代
box.remove()
3.replaceChild(新的,老的)替换节点
var odiv2=document.creatElement("div")
odiv2.innerHTML="22222"
box.replaceChild(odiv2,child)
4.cloneNode()克隆节点
括号里面不写参数的话,默认false,不克隆后代
var oCloneBox = box.cloneNode()
//往页面里插入
document.body.appendChild(oCloneBox)
括号里写(true)就是克隆全部。 但是这样会造成因为完全克隆导致id相同
var oCloneBox = box.cloneNode(true)
oCloneBox.id="box2"
//往页面里插入
document.body.appendChild(oCloneBox)
动态删除案例
下面用到的这个方法相较于map的方法来说,绑事件更加方便,所以我们用这个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="list">
<!-- <li></li>
<li></li>
<li></li> -->
</ul>
<script>
var arr=["111","222","333"]
//循环遍历
for(var i=0;i<arr.length;i++){
//直接在这添加li
var oli=document.createElement("li")
oli.innerHTML=arr[i]
//li是父节点,所以button应该放在li(oli)里
var obutton = document.createElement("button")
obutton.innerHTML="delete"
//绑定一个事件
obutton.onclick=handler
//也就是在遍历每个i时,追加一个按钮在后面
oli.appendChild(obutton)
list.appendChild(oli)
}
function handler(){
console.log(this)
//用this可以避免用索引设置获取的麻烦
this.parentNode.remove()
}
</script>
</body>
</html>
节点属性
找元素节点的方式:nodeType===数字
(可通过if循环找)
1为元素节点,2为属性节点,3为文本节点,8为注释节点
获取元素尺寸
就是元素的“占地面积”
offsetWith
offsetHeight
clientWidth
clientHeight
1.获取到的尺寸是没有单位的数字
2.如果元素display:none了,就获取不到了
3.box-sizing:border-box(设置什么宽高就是什么宽高,如果有边距就会挤压里面内容)正常使用
获取元素的偏移量(上下左右)
1. 相对于定位父级(遇到的第一个有定位的父级)
如果父级元素都没有定位,偏移量就相对于body
offsetTop
offsetBottom
offsetLeft
offsetRight
2. 其实计算的就是边框宽度
clientTop
clientBottom
clientLeft
clientRight
DOM获取可视窗口的尺寸
bom计算滚动条宽度,dom不计算
懒加载案例+另外一种渲染写法
document.documentElement.scrolltop获取滚动距离
如果是想要快到底的效果,就需要加一个isLoading。这样就不会频繁触发到底
isLoading = false
if(isLoading)return
if(listHeight+listTop-Math.round(windowHeight+scrollTop)<100){
console.log("快到底咯")
isLoading = true
}
一般就是
if(Math.round(windowHeight+scrollTop)===listHeight+listTop){
console.log("到底咯")
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.content {
width: 500px;
background-color: yellowgreen;
}
li {
height: 150px;
list-style: none;
line-height: 30px;
}
li img {
float: left;
width: 100px;
}
</style>
</head>
<body>
<!-- <div class="nav">
<ul>
<li>正在热映</li>
<li>即将上映</li>
</ul>
</div> -->
<div class="content">
<ul id="list">
<!-- <li></li>
<li></li>
<li></li> -->
</ul>
</div>
<script>
var filmList = [
{
url: "https://pic.maizuo.com/usr/movie/6f0850b4fc5e0ddfaac2e8146c23e21c.jpg?x-oss-process=image/quality,Q_70",
title: "拯救嫌疑人",
garde: "7.7",
major: "张末 张小斐 李鸿其 惠英红 王子异",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6766e8827df785bbc5f9acc1efff8241.jpg?x-oss-process=image/quality,Q_70",
title: "河边的错误",
garde: "7.5",
major: "魏书钧 朱一龙 曾美慧孜 侯天来 佟林楷",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/291ad328f0db1bb68a4386edbf3f3ab0.jpg?x-oss-process=image/quality,Q_70",
title: "汪汪队立大功大电影2:超能大冒险",
garde: "7.8",
major: "卡尔·布伦克尔 天天 阿奇 莱德队长 贝贝",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6f0850b4fc5e0ddfaac2e8146c23e21c.jpg?x-oss-process=image/quality,Q_70",
title: "拯救嫌疑人",
garde: "7.7",
major: "张末 张小斐 李鸿其 惠英红 王子异",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6766e8827df785bbc5f9acc1efff8241.jpg?x-oss-process=image/quality,Q_70",
title: "河边的错误",
garde: "7.5",
major: "魏书钧 朱一龙 曾美慧孜 侯天来 佟林楷",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/291ad328f0db1bb68a4386edbf3f3ab0.jpg?x-oss-process=image/quality,Q_70",
title: "汪汪队立大功大电影2:超能大冒险",
garde: "7.8",
major: "卡尔·布伦克尔 天天 阿奇 莱德队长 贝贝",
region: "中国大陆|156分钟"
}
]
var filmList2 = [
{
url: "https://pic.maizuo.com/usr/movie/6f0850b4fc5e0ddfaac2e8146c23e21c.jpg?x-oss-process=image/quality,Q_70",
title: "拯救嫌疑人",
garde: "7.7",
major: "张末 张小斐 李鸿其 惠英红 王子异",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6766e8827df785bbc5f9acc1efff8241.jpg?x-oss-process=image/quality,Q_70",
title: "河边的错误",
garde: "7.5",
major: "魏书钧 朱一龙 曾美慧孜 侯天来 佟林楷",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/291ad328f0db1bb68a4386edbf3f3ab0.jpg?x-oss-process=image/quality,Q_70",
title: "汪汪队立大功大电影2:超能大冒险",
garde: "7.8",
major: "卡尔·布伦克尔 天天 阿奇 莱德队长 贝贝",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6f0850b4fc5e0ddfaac2e8146c23e21c.jpg?x-oss-process=image/quality,Q_70",
title: "拯救嫌疑人",
garde: "7.7",
major: "张末 张小斐 李鸿其 惠英红 王子异",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/6766e8827df785bbc5f9acc1efff8241.jpg?x-oss-process=image/quality,Q_70",
title: "河边的错误",
garde: "7.5",
major: "魏书钧 朱一龙 曾美慧孜 侯天来 佟林楷",
region: "中国大陆|156分钟"
},
{
url: "https://pic.maizuo.com/usr/movie/291ad328f0db1bb68a4386edbf3f3ab0.jpg?x-oss-process=image/quality,Q_70",
title: "汪汪队立大功大电影2:超能大冒险",
garde: "7.8",
major: "卡尔·布伦克尔 天天 阿奇 莱德队长 贝贝",
region: "中国大陆|156分钟"
}
]
renderHTML(filmList)
function renderHTML(arr) {
list.innerHTML += arr.map(function (item) {
return `<li>
<img src="${item.url}">
<h3>${item.title}</h3>
<p>观众评分:${item.garde}</p>
<p>主演:${item.major}</p>
<p>${item.region}</p>
</li>`
}).join("")
}
//但是到这里还不行,因为你这个map映射到页面中会自动转成字符串,所以每个之间就会有,连接
//所以这里用到join属性
//这种方式可以避免页面加载一页闪了一下
/*function renderHTML(filmList){
for(var i=0;i<filmList.length;i++){
var oli = document.createElement("li")
oli.innerHTML =`<li>
<img src="${item.url}">
<h3>${item.title}</h3>
<p>观众评分:${item.garde}</p>
<p>主演:${item.major}</p>
<p>${item.region}</p>
</li>
`
list.appendChild(oli)
}
}*/
isLoading = false
//ul
window.onscroll = function () {
var listHeight = list.offsetHeight
var listTop = list.offsetTop
console.log(listHeight + listTop)
//有兼容性问题
var scrollTop = document.documentElement.scrollTop ||
document.body.scrollTop
var windowHeight = document.documentElement.clientHeight
console.log(Math.round(windowHeight + scrollTop))//看是否到底
if (isLoading) return
if (listHeight + listTop - Math.round(windowHeight + scrollTop) < 50) {
console.log("快到底咯")
isLoading = true
//干正事了,渲染下一页
//(上面map那里要改成+=,不然渲染下一页的时候会直接覆盖上一页)
//renderHTML(filmList2)
//但是跟后端要数据会稍微慢一点,所以我们这样写
setTimeout(function () {
renderHTML(filmList2)
isLoading=false//下一次到底事件继续触发
}, 1000)
}
}
</script>
</body>
</html>
事件
绑定方式
dom0绑定方式
用dom0绑事件就必须加on
如果再次绑定,会被新的覆盖
var oDiv=document.querySelector(`div`)
oDiv.onclick=function(){
//执行代码
}
dom2 可以绑定多个,按顺序执行
有兼容,低版本6,7,8不行 box.attachEvent("onclick",function(){})
//给box绑了一个事件处理器
box.addEventListener("click",function(){
console.log("111111")
})//click是事件类型
box.addEventListener("click",function(){
console.log("222222")
})
box.addEventListener("click",function(){
console.log("333333")
})
事件解绑
原来用的是这个禁用属性,但是前端完全可以在检查中把disabled属性去掉
btn.onclick=function(){
console.log("谢谢惠顾")
//this拿到的是这个按钮
this.disabled="disabled"
}
dom0解绑
dom节点.onclick=null
btn.onclick=function(){
console.log("谢谢惠顾")
this.onclick=null
}
dom2解绑
兼容性btn.detachEvent("onclick",handler)在事件里写
这里我们用一下封装函数
两把钥匙,都指向一个function房间(同一个回调函数)
function handler(){
console.log("谢谢惠顾")
}
btn.addEvenListener("click",handler)
btn.removeEventListener("click",handler)
事件类型
浏览器事件/鼠标事件/键盘事件/表单事件/触摸事件
浏览器事件
load页面全部资源加载完毕
scroll浏览器滚动的时候触发
鼠标事件
click点击事件
dblclick双击事件
contextmenu右键单击事件(常用于自定义右键菜单)
mousedown鼠标左键按下事件(按下就没有反悔的机会了,即刻触发)
mouseup鼠标左键抬起事件
mousemove鼠标移动
mouseover mouseout移入移出(孩子也会触发)
mouseenter mouseleave移入移除(孩子不会触发)
键盘事件
比如你按下回车键就可以提交,不一定非要按按钮,所以可以给键盘绑一个事件
keyup键盘抬起事件
keydown键盘按下事件
keypress键盘按下再抬起事件
表单事件
focus获取焦点
blur失去焦点
(可用于你输入完离开时,判断你输入的内容是否符合要求)
<input type="text" id="username">
<script>
username.onfocus=function(){
console.log("获取焦点")
}
username.onblur=function(){
console.log("失去焦点")
}
</script>
change表单内容改变事件(前提是:在获取焦点与失去焦点的对比里面内容不一样才会触发)
input表单内容输入事件(每次内容不一样都触发,也就是每打一个字就触发)
这个的 前提 是body里必须有表单结构
<form action=""></form>
与上面那些给单独的input绑之外,这个不一样,因为是form要提交,form要重置,所以给form绑
submit表单提交事件(默认跳转,马上提交)
而我们如果需要对内容判断,就要想阻止它马上提交,用return false就可以
reset重置
触摸事件(只针对移动端)
touchstart触摸开始事件
touchend触摸结束事件
touchmove触摸移动事件
touchcancel
事件对象
event,其实就是一个形参
鼠标事件
鼠标跟随案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
#box{
width: 200px;
height: 50px;
background-color: yellow;
position: relative;
}
#box p{
width: 300px;
height: 200px;
background-color: aquamarine;
position: absolute;
left: 100px;
top: 100px;
display: none;
/* 法二 */
/* 穿透,也就是鼠标放上去之后也不会到p标签上
“鼠标事件”*/
pointer-events: none;
}
</style>
</head>
<body>
<div id="box">
kerwin头像
<p>kerwin头像kkk</p>
</div>
<script>
box.onmouseover=function(){
this.firstElementChild.style.display="block"
}
box.onmouseout=function(){
this.firstElementChild.style.display="none"
}
box.onmousemove=function(evt){
console.log(evt.offsetX,evt.offsetY)
// 法一,可以直接再加50距离(不太规范,但是可行)
this.firstElementChild.style.left=evt.offsetX+"px"
this.firstElementChild.style.top=evt.offsetY+"px"
}
</script>
</body>
</html>
鼠标拖拽案例
这个的问题是,当你点击鼠标的时候,box会马上移动,使你的鼠标在你写的这个左上角,但是我们其实想让鼠标点上之后一直处于中间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
background-color: aquamarine;
position:absolute;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
box.onmousedown=function(){
document.onmousemove=function(evt){
//这里的问题!!!!!!!!
box.style.left=evt.clientX+"px"
box.style.top=evt.clientY+"px"
}
}
box.onmouseup=function(){
document.onmousemove=null
}
</script>
</body>
</html>
应该改成这样
box.onmousedown=function(){
document.onmousemove=function(evt){
var x=evt.clientX-box.offsetWidth/2
var y=evt.clientY-box.offsetHeight/2
box.style.left=x+"px"
box.style.top=y+"px"
}
}
因为
但是现在还存在的问题是你这个box如果移动到边距处,它会出去,所以我们加一个if判断:
当y<=0时,给y赋值0,那么box就不会出去了
box.onmousedown=function(){
document.onmousemove=function(evt){
var x=evt.clientX-box.offsetWidth/2
var y=evt.clientY-box.offsetHeight/2
if(y<=0)y=0
if(x<=0)x=0
if(x>=document.documentElement.clientWidth-
box.offsetWidth)x=document.documentElement.clientWidth-
box.offsetWidth
if(y>=document.documentElement.clientHeight-
box.offsetHeight)y=document.documentElement.clientHeight-
box.offsetHeight
box.style.left=x+"px"
box.style.top=y+"px"
}
}
还有一种方法
这样可以避免嵌套,也可以不用事件解绑
isDown=false
box.onmousedown=function(){
isDown=true
}
box.onmouseup=function(){
//这种写法就不用写这个解绑了
//document.onmousemove=null
isDown=false
}
document.onmousemove=function(evt){
if(!isDown)return
var x=evt.clientX-box.offsetWidth/2
var y=evt.clientY-box.offsetHeight/2
if(y<=0)y=0
if(x<=0)x=0
if(x>=document.documentElement.clientWidth-
box.offsetWidth)x=document.documentElement.clientWidth-
box.offsetWidth
if(y>=document.documentElement.clientHeight-
box.offsetHeight)y=document.documentElement.clientHeight-
box.offsetHeight
box.style.left=x+"px"
box.style.top=y+"px"
}
DOM事件的传播
阻止事件传播
这里我们用的案例是动态删除,我们想做到的效果是:在你点前面的li文字时可以跳转页面,再点击后面按钮时可以删除
但是如果你此时只给li绑一个onclick事件,你点了删除之后依然会跳转,这是因为冒泡触发,所以我们需要再在下面加一个阻止传播
有低版本ie有兼容问题,具体修改方案看千锋视频p105
阻止默认行为(有校验的需求时)
之前我们在表单提交那里用过这个return false
1.dom0,这个没有兼容性
2.dom2,有兼容
右键自定义菜单
事件委托
优点: 减少多个函数的绑定的性能损耗;动态添加li,也会有事件处理
给孩子做的事,给父亲做,可以不用每一个孩子一个一个做
但是我们该如何知道是点了哪个孩子呢
target是触发事件的人
dom0写法
<body>
<ul>
<li>111111
<button>add</button></li>
</ul>
<script>
list.onclick=function(evt){
console.log(evt.target)
}
</script>
</body>
这种方法,我们结合上面右键自定义菜单就可以实现,点哪个就知道是哪个,即
低版本ie兼容性,在事件中要写成或的形式