元素节点的获取
要想对dom元素进行操作,必须先获取到这个节点,才能进行操作
获取元素的三种方式
<body>
<button id="btn">点击</button>
<div class="item"></div>
<a href="#">超链接</a>
</body>
<script>
// 通过元素唯一的id来获取元素 id是唯一的
var btn = document.getElementById("btn");
console.log(btn);
//通过元素的类名 来获取此节点
var item = document.getElementsByClassName("item");
console.log(item);
//通过获取标签名 把节点取出来
var alink = document.getElementsByTagName("a");
console.log(alink);
</script>
既然方式二、方式三获取的是标签数组,那么习惯性是先遍历之后再使用。
特殊情况:数组中的值只有1个。即便如此,这一个值也是包在数组里的。这个值的获取方式如下:
<body>
<div class="item">你好</div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</body>
<script>
// 获取所有div中的第一个div
var div = document.getElementsByTagName("div")[0];
console.log(div);
</script>
事件对象的内部的this
在事件对象的内部,有一个this,它指向的是事件源
- this的指向,谁触发的事件,谁调用的,this就指向谁
不同函数内部this的指向
- 普通函数 ----------------> window对象
- 构造函数 -----------------> 指向的是生成的实例对象
- 对象的方法 --------------> 指向的是对象本身
- 事件函数 -----------------> 指向的是事件源
显示隐藏
<!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>
<style>
#item {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<button>显示</button>
<div id="item"></div>
</body>
<script>
//获取元素
var btn = document.querySelector('button');
var item = document.getElementById('item');
//定义变量,控制显示隐藏
var num = 1;
btn.onclick = function () {
if (num === 1) {
//当num的值为1的时候点击按钮将div隐藏,再将按钮内部的文字替换掉
this.innerText = '隐藏';
item.style.display = 'none';
num = 2;
} else {
this.innerText = '显示';
item.style.display = 'block';
num = 1;
}
}
</script>
</html>
相册案例
- 过程
- 获取元素(事件源。谁触发的事件)
- 给获取的元素添加点击事件,用for循环遍历,给每一个超链接添加点击事件
- 更改img内部src属性值,使用this,指向事件源
- 更改p标签内部的文字内容;
- 取消a标签的跳转
<body>
<h2>城市街道</h2>
<div class="so">
<a href="img/1.jpeg" title="街道1">
<img style="width:100px" src="img/001.jpeg" alt="">
</a>
<a href="img/2.jpeg" title="街道2">
<img style="width:100px" src="img/002.jpeg" alt="">
</a>
<a href="img/3.jpeg" title="街道3">
<img style="width:100px" src="img/003.jpeg" alt="">
</a>
<a href="img/4.jpeg" title="街道4">
<img style="width:100px" src="img/004.jpeg" alt="">
</a>
</div>
<div class="bg ">
<img id="imgs" src="" alt="">
</div>
<p>请选择图片</p>
</body>
<script>
//获取元素
var so = document.querySelector('.so');
var aLi'[;.nks = so.getElementsByTagName('a');
var imgs = document.getElementById('imgs');
var txt = document.querySelector('p');
//遍历数组。添加点击事件
for(var i = 0; i < aLinks.length; i++){
aLinks[i].onclick = function(){
//更改img的内部的src的属性值
imgs.src = this.href;
//更改p标签内部的文字的内容
txt.innerHTML = this.title;
return false;
}
}
</script>
DOM里面取消a标签跳转默认效果
return false;
在事件函数内部书写这个语句
for循环内部添加的绑定事件,在触发时,所有添加的事件已经添加成功了,触发事件时是循环之后在触发的事件
批量绑定的事件函数的内部,如果有变量i, 注意,函数执行是已经是循环结束后
循环内部定义的变量是一个全局变量,在循环后执行的I变量的值I跳出循环的值
使用this来获取a标签内部的href属性,this的指向,是触发事件的事件源
获取标签内部的内容innerText,innerHTML
对比使用场景
- innerText:在设置纯文本,不包含标签
- innerHTML:在设置有子标签解构的时候使用,在设置的时候也可以在内部写html标签
- innerHTML设置属性是,会按照html的语法中的标签加载
var div = document.querySelector('div');
console.log(div);
div.innerHTML = '<h2>你好ya</h2>'
表单元素属性
| 属性 | 含义z | |
|---|---|---|
| value | 获取大部分表单内容,除了option以外 | |
| type | 可以获取input标签类型 | |
| disabled | 禁z | |
| checked | 复选框 | |
| selected | 下拉菜单 |
!!注意,在DOM中对象的属性值只有一个时候,或被转换成布尔值,属性名与属性值相同。可以直接赋值为true
验证表单案例
<!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>
.gr{
border: 5px solid green;
}
.re{
border: 5px solid red;
}
</style>
</head>
<body>
<input type="text" id = "name">
<input type="password" id = "password">
<input type="button" id = "btn" value="提交">
</body>
<script>
//检测用户输入的用户名是否是3-6位,密码是否是6-8位,要是不满足,需要高亮显示输入框
//获取元素
var text = document.getElementById('name');
var password = document.getElementById('password');
var btn = document.getElementById('btn');
btn.onclick = function() {
//用户名
if(text.value.length < 3 || text.value.length > 6){
text.className = 're';
//如果他不成立就不要再进行下一步
return;
}else{
text.className = 'gr';
}
if(password.value.length < 6 || password.value.length > 8){
password.className = 're';
//如果他不成立就不要再进行下一步
return;
}else{
password.className = 'gr';
}
console.log('提交成功');
}
</script>
</html>
随机下拉菜单案例
<!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>
<button>选择</button>
<select id="name">
<option>拉面</option>
<option>牛肉面</option>
<option>安徽板面</option>
<option>兰州拉面</option>
<option>大碗宽面</option>
<option>担担面</option>
</select>
</body>
<script>
//获取元素
var btn = document.querySelector('button');
var select = document.getElementById('name');
var option = select.querySelectorAll('option');
btn.onclick = function(){
//随机选择option 每次点击需要获取一个数组随机下标
//定义一个接收随机数的变量;
//运用math对象里面的向上取整与随机生成数字的方法,来获取随机值 在乘以随机的值的长度,就可以得到一个在0-5之间的随机数
var p = Math.floor(Math.random() * option.length);
//随机出来的数对应html 里的option下标值
select[p].selected = true;
//在这里,dom里面,表单这一块,属性名与属性值名字相同,返回的值是true,不写是false 或者是空,
//他的这个可以是true,要是一户参与其他程序,方便使用
}
</script>
</html>
在使用math对象里面的random方法是,他生成的是【0,1)之间的数字 ,左边是闭区间,右面是开区间,设置随机生成数字就是方法乘以他的长度,就可以随机出0-5之间的随机数,更好的写法就是 random() * opts.length的长度 当一个选项删除会这是增加一项,就不会再次更改代码
搜索框案例
<!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>
.bg{
color:black;
}
.gr{
color: gray;
}
</style>
</head>
<body>
<input type="text" id = "text" value="请输入用户名">
<button>点击按钮</button>
</body>
<script>
//获取元素
var text = document.getElementById("text");
//获取焦点 要是内容为空,那么文字是灰色的
text.onfocus = function() {
if( text.value == '请输入用户名' ){
text.className = 'bg';
text.value = '';
}
}
//失去焦点
text.onblur = function() {
//如果用户书写的整好是value的值,为了保证用户的视觉体验,
//需要在添加一个条件就是当内容和value值相同时候,文字变成灰色
if(text.value == '' || text.value =='请输入用户名'){
text.value = '请输入用户名';
text.className = 'gr'
}
}
</script>
</html>
自定义属性
元素自定义的属性是不可以通过点的形式来调用
- 1 getAttribute('属性')
<!-- 在这里data-index是自定义属性值 -->
<div data-index="1"></div>
var div = document.querySelector("div");
console.log(div.getAttribute("data-index"));
- 2 设置元素属性值 (针对自定属性值)
// 括号里面的值是 自定义属性名 属性值
div.setAttribute("data-index", 2);
这里自定义属性setAttribute里面的值,如果是添加的是class这个名字,不需要将他更改,因为里面的值是字符串类型的,与js内部定义好的值是不冲突的,所以不需要更改名字
- 3 移除属性值 removeAttribute('自定义属性值')
div.removeAttribute("data-index");
在之后书写代码上,如果是定以过的属性,尽量去使用点取调用,而自定义的属性使用到的是他们三个
style样式属性操作
得到的值是行内样式,只能获取的是行内的样式,外联的样式不可以获取到的
补充:在获取元素时候,我们可以将获取元素的方法封装到函数里面,放在公共文件内,在使用时候,直接调用函数就可以了
function my$(id){
return document.getElementById(id)
}
var btn = my$('btn')
上面个封装的是获取元素id的函数,通过调用函数传入id,可以实现获取元素,通过id的方式
- 类似background-color 这样单一复合的属性,需要通过使用驼峰命名的方法第二个单词首字母大写
- 在通过style属性设置行内样式的时候,值的类型是字符串,需要在后面加上px单位
样式操作的选择(何种方式)
实际工作中改如何选择设置样式的方法
- 很多个样式需要进行设置,就会选择使用class类名的方式进行更改
- 一条或者是两条css样式,可以通过行内的方式进行操作
js里面单独获取body 通过document.body的方式来获取body标签
切换案例的思路
两种方式
- 没办法通过全等或者是相等的判断,可以定义一个变量来进行管理
- 如果可以通过全等或者是相等的条件进行判断,可以直接使用全等/相等进行书写,减少代码量,减少定义变量
排他思想
在对批量添加只让自己做什么事情的时候,可以用到派他思想
- 排除其他 通过使用循环,将所有的元素都去除,把所有内容包括自己样式去掉
- 留下自己,把自己独有的样式进行设置
设置元素位置大小需要注意的问题
在设置元素大小或者是位置问题上,js代码是没问题,但是问题出在了css上,在给元素添加大小或者是移动位置,都需要给元素添加定位。
隔行变色案例,鼠标悬停
在这里巧妙的运用了一个全局变量,这个全局变量,当鼠标移入的时候,先记录一下自身的颜色,然后在进行更改,当鼠标离开的时候,将原来的颜色重新给backgroundcolor;实现鼠标鼠标移入变色
对应控制思想(tab案例)
有两组数据中储存了相同个数的元素对象,一组对象发生变化,另一组也会发生变化
实现方法
- 找两个数据中的共同点,两个数组中元素的下标是一样的
- 在对应控制思想中也会有排他思想
<!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;font-size: 15px;}
.container { width: 500px; height: 200px;background-color: pink;}
.tab {
width: 100%;display: flex;align-items: center;color: white;background-color: black; border-bottom: 1px solid black;
}
span {flex: 1;text-align: center; padding: 10px 0px; border: 1px solid pink;margin-left: -1px;cursor: pointer;
}
.tab .active {background-color: pink; color: black;transition: .5s;
}
.item .active {display: block;color: black;
}
.item>div {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="tab" id="tab">
<span class="active">新闻</span>
<span>娱乐</span>
<span>影视</span>
<span>话题</span>
</div>
<div class="item" id="item">
<div class="active">新闻</div>
<div>娱乐</div>
<div>影视</div>
<div>话题</div>
</div>
</div>
</body>
<script>
//获取元素
var span = document.getElementById('tab').querySelectorAll('span');
var item = document.getElementById('item').querySelectorAll('div');
//鼠标悬停导航栏切换类名
for (var i = 0; i < span.length; i++) {
span[i].index = i;
span[i].onmouseover = function () {
//给span添加属性 每一个span都有下标 从0-3
//排他思想,将选项全部排除,自己包括在内
for (var j = 0; j < span.length; j++) {
span[j].className = '';
item[j].className = '';
}
//添加类名
this.className = 'active';
//给div添加类名 span下标是多少 ,这个相同的div的下标是多少
item[this.index].className = 'active';
}
}
</script>
</html>
Dom节点
创建节点 createElement
格式
新的标签(元素笔记)获取的父节点(ul)=document.createElement("标签名字")
代码案例
let item = document.createElement("div");
console.log(item);
插入节点
注意!: 在插入节点这里需要注意的是,必须先创建节点,才能将创建好的节点插入到元素内部
方式一.appendChild
格式:
父节点(通过获取节点把父节点获取到).appendChild(创建新的子节点的名字)
代码举例
<body>
<ul>
<li>你好</li>
<li>我好</li>
</ul>
</body>
<script>
// 创建节点
let li = document.createElement("li");
let ul = document.querySelector("ul");
// 将节点插入到ul里面
ul.appendChild(li);
console.log(ul);
</script>
删除节点removeChild
格式:
父节点.removeChild(子节点)
复制节点(克隆节点)
格式如下:
要复制的节点.cloneNode(); //括号里不带参数和带参数false,效果是一样的。
要复制的节点.cloneNode(true);
括号里带不带参数,效果是不同的。解释如下:
不带参数/带参数false:只复制节点本身,不复制子节点。
带参数true:既复制节点本身,也复制其所有的子节点。
代码实例
<body>
<ul>
<li>你好</li>
<li>我好</li>
</ul>
</body>
<script>
var ul = document.querySelector("ul");
var li1 = document.createElement("li");
ul.appendChild(li1);
//定义变量接收复制的节点
var li2 = li1.cloneNode();
// 将复制的节点添加到ul里面
ul.appendChild(li2);
console.log(ul);
</script>
点击a标签不跳转
<a href = "javascript:void(0);"></a>
注册事件的其他方法
addEventListener()
参数解释:
参数1:事件名的字符串(注意,没有on)
参数2:回调函数:当事件触发时,该函数会被执行
参数3:true表示捕获阶段触发,false表示冒泡阶段触发(默认)。如果不写,则默认为false。【重要】
代码例子
<body>
<div></div>
</body>
<script>
var div = document.querySelector('div')
div.addEventListener('click', function () {
alert('hello')
})
</script>
addEventListener使用方式
代码量较多可使用此方法
<body>
<button>点击事件</button>
</body>
<script>
var btn = document.querySelector('button')
btn.addEventListener('click', mo)
btn.addEventListener('click', mo1)
function mo() {
alert('htllo')
}
function mo1() {
alert('htllo')
}
</script>
注意 事件监听方法 可以对一个标签绑定多个事件而前面的事件不会被覆盖掉 依然进行
/*
需要3个值
1. type : 事件类型比如说 点击事件
2. listener :事件处理函数
3. useCapture :可选参数默认false
同一个元素可以添加多个事件
*/
btn.addEventListener("click", () => {});
移除事件
<div>1</div>
- 1 传统方式解除绑定事件
var div = document.querySelector("div");
div.onclick = function () {
alert("你好");
//解除事件
div.onclick = null;
};
attachEvent()
注册事件兼容写法(自定义)
var btn = document.getElementById("btn");
// 调用函数
addEvent(btn, "click",fn);
//为了更好的解绑事件函数单独拿出来
function fn() {
alert(1);
}
// DOM 2 级事件绑定方式
// 自己制作一个兼容所有浏览器的绑定事件的函数
// 参数:事件源,事件类型,事件函数
function addEvent(ele, type, fn) {
// IE 9 及以上的浏览器和其他浏览器,使用 addEventListener 方法
// IE 9 以下的浏览器,使用 attachEvent 方法
// 浏览器能力检测
if (ele.addEventListener) {
ele.addEventListener(type, fn);
} else if (ele.attachEvent) {
ele.attachEvent("on" + type, fn);
}
}
- 删除监听事件
var div = document.querySelector("div");
div.addEventListener("click", fn); //fn不需要调用
//可以把事件处理程序 提出来放在外面
function fn() {
alert("你好");
//移除监听事件
div.removeEventListener("click", fn);
}
移除事件兼容写法(自定义)
// 移除事件
removeEvent(btn,"click",fun);
function fun() {
alert(1);
}
// 兼容所有浏览器的 解除绑定事件的函数
// 参数:事件源,事件类型,事件函数
function removeEvent(ele,type,fn) {
// 浏览器能力检测
if (ele.removeEventListener) {
ele.removeEventListener(type,fn);
} else if (ele.detachEvent) {
ele.detachEvent("on" + type,fn);
}
}
Dom事件流
addEventListener有三个值,第三个值是用来决定事件流
- 参数值是布尔值,false是标识冒泡 ,true是捕获的过程
先进行捕获后进行冒泡
什么情况下会出现冒泡捕获
祖先级与目标元素同时绑定了相同的事件,再过点击目标元素的过程中,两种执行指向事件的方向
- 从文档Document开始向下一层一层的向下捕获
- 从目标元素开始向上div开始,一直到文档Document结束,是冒泡
事件流的三个阶段
• 第一个阶段:事件捕获
• 第二个阶段:事件执行过程
• 第三个阶段:事件冒泡
分别表示摸一个元素,元素绑定的事件执行的处于哪一个阶段
• onclick 类型:只能进行事件冒泡过程,没有捕获阶段
box1.onclick = function () {
console.log(1);
};
box2.onclick = function () {
console.log(2);
};
box3.onclick = function () {
console.log(3);
};
控制台输出
3
2
1
• attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
事件委托
利用事件冒泡,将子级的事件委托给父级加载 于此同时,需要利用事件函数的一个 e 参数,内部存储的是事件对象
什么时候用到事件委托?
案例:点击变色
<ul id="list">
<li>朴彩英</li>
<li>郑秀妍</li>
<li>金智妮</li>
<li>金智秀</li>
<li>lisa</li>
</ul>
<script>
// 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加
// 以前的思路:获取所有的 li 标签元素,批量添加事件
// 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源
// 获取元素
var list = document.getElementById("list");
var lis = list.children;
// 给 ul 添加点击事件
list.onclick = function (e) {
// 在内部要想办法找到真正触发事件的 li
// 借用事件函数内部的一个参数 e,e 是事件对象
// 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据
// e.target 属性记录的就是真正触发事件的事件源
// 排除其他
for (var i = 0 ; i < lis.length ; i++) {
lis[i].style.backgroundColor = "";
}
e.target.style.backgroundColor = "pink";
};
</script>
思路:事件委托
事件对象
只要触发事件,就会有一个对象,内部存储了与事件相关的数据
**e 在低版本浏览器中有兼容问题,低版本浏览器使用的是 window.event **
处理e在低版本浏览器的兼容问题
function fn(e){
e = e || window.event;
}
解释:
当e对象在高版本浏览器里面,对e进行判断,浏览器要是可以识别,就会返回true,如果低版本在使用e对象对象的时候,识别不出来e对象,那么返回的是false,然后e对象的值就是window.event
事件对象常用属性
e.target获取真正触发事件对象
兼容写法
var target = e.target || e.srcElement;
e.clientX/e.clientY
event调用:
- clientX:鼠标距离可视区域左侧距离。
- clientY:鼠标距离可视区域上侧距离。
**所有浏览器都支持,鼠标距离浏览器窗口左上角的距离 **
e.pageX/e.pageY
IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离
案例:鼠标移动,图片跟随鼠标移动
思路:
- 给整个文档添加鼠标移动事件
- 获取鼠标在整个文档里的坐标clientX与clirentY
- 将获得的位置设置给图片,
!! 在设置图片的css注意,一定是绝对定位或者是固定定位,因为这样图片在移动过程中,不会影响到其他元素,将获取到的坐标分别给图片的left值与top值,在赋值是需要注意,要加上单位
阻止事件冒泡
大部分情况下,冒泡都是有益的。当然,如果你想阻止冒泡,也是可以的。可以按下面的方法阻止冒泡。
阻止冒泡的方法
w3c的方法:(火狐、谷歌、IE11)
event.stopPropagation();
IE10以下则是:
event.cancelBubble = true
兼容代码如下:
box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
上方代码中,我们对box3进行了阻止冒泡,产生的效果是:事件不会继续传递到 father、grandfather、body了。
不是所有的事件都能冒泡
以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave。意思是,事件不会往父元素那里传递。
DOM特效
JS动画的主要内容如下:
1、三大家族和一个事件对象:
三大家族:offset/scroll/client。也叫三大系列。
事件对象/event(事件被触动时,鼠标和键盘的状态)(通过属性控制)。
2、动画(闪现/匀速/缓动)
3、冒泡/兼容/封装
偏移量属性 offset系列
js中有一套方便的获取元素尺寸的办法就是offset家族。offset家族包括:
- offsetWidth
- offsetHight
- offsetLeft
- offsetTop
- offsetParent
1、offsetWidth 和 offsetHight
offsetWidth 和 offsetHight:获取元素的宽高 + padding + border,不包括margin。如下:
offsetWidth = width + padding + border
offsetHeight = Height + padding + border
这两个属性,他们绑定在了所有的节点元素上。获取元素之后,只要调用这两个属性,我们就能够获取元素节点的宽和高。
2、offsetParent
offsetParent:获取当前元素的定位父元素。
如果当前元素的父元素,有CSS定位(position为absolute、relative、fixed),那么
offsetParent获取的是最近的那个父元素。如果当前元素的父元素,没有CSS定位(position为absolute、relative、fixed),那么
offsetParent获取的是body。
3、offsetLeft 和 offsetTop
offsetLeft:当前元素相对于其定位父元素的水平偏移量。
offsetTop:当前元素相对于其定位父元素的垂直偏移量。
备注:从父亲的 padding 开始算起,父亲的 border 不算在内。
!!!! 注意,如果父级元素没有定位,那么获取的就是,相对于body,从左上开始,那么就
**是,如果获取的是子元素距离body的距离就是 **
**父级margin+父级border+子元素的magrin / 父级的padding **
offsetLeft 和 style.left 区别
(1)最大区别在于:
offsetLeft 可以返回无定位父元素的偏移量。如果父元素中都没有定位,则body为准。
style.left 只能获取行内样式,如果父元素中都没有设置定位,则返回""(意思是,返回空字符串);
(2)offsetTop 返回的是数字,而 style.top 返回的是字符串,而且还带有单位:px。
比如:
div.offsetLeft = 100;
div.style.left = "100px";
(3)offsetLeft 和 offsetTop 只读,而 style.left 和 style.top 可读写(只读是获取值,可写是修改值)
总结:我们一般的做法是:用offsetLeft 和 offsetTop 获取值,用style.left 和 style.top 赋值(比较方便)。理由如下:
style.left:只能获取行内式,获取的值可能为空,容易出现NaN。
offsetLeft:获取值特别方便,而且是现成的number,方便计算。它是只读的,不能赋值。
客户端大小 client 家族的组成
只于自身的元素有关系
1、clientWidth 和 clientHeight(常用)
元素调用时:
clientWidth:获取元素的可见宽度(width + padding)。
clientHeight:获取元素的可见高度(height + padding)。
body/html 调用时:
clientWidth:获取网页可视区域宽度。
clientHeight:获取网页可视区域高度。
声明:
-
clientWidth和clientHeight属性是只读的,不可修改。 -
clientWidth和clientHeight的值都是不带 px 的,返回的都是一个数字,可以直接进行计算。
!!! 注意,client获取的是不包括边框的元素大小
滚动偏移属性
scrollLeft:获取水平滚动条滚动的距离。scrollTop:获取垂直滚动条滚动的距离。
实战经验:
当某个元素满足scrollHeight - scrollTop == clientHeight时,说明垂直滚动条滚动到底了。
当某个元素满足scrollWidth - scrollLeft == clientWidth时,说明水平滚动条滚动到底了。
这个实战经验非常有用,可以用来判断用户是否已经将内容滑动到底了。比如说,有些场景下,希望用户能够看完“长长的活动规则”,才允许触发接下来的表单操作。
获取 html 文档的方法
获取title、body、head、html标签的方法如下:
document.title文档标题;document.head文档的头标签document.body文档的body标签;document.documentElement(这个很重要)。
document.documentElement表示文档的html标签。也就是说,基本结构当中的 html 标签而是通过document.documentElement访问的,并不是通过 document.html 去访问的。
滚动事件onscroll()
当我们用鼠标滚轮,滚动网页的时候,会触发 window.onscroll() 方法。
模态框拖拽
<!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>
<style>
#item {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 300px;
border: 5px solid #556874;
}
#item .dpan {
width: 100%;
height: 50px;
background: beige;
position: relative;
}
.dpan button {
position: absolute;
right: 0;
top: 50%;
transform: translate(-50%, -50%);
}
.pan {
background-color: pink;
width: 100%;
height: 250px;
}
</style>
<body>
<div id="item">
<div class="dpan">
<button>关闭</button>
</div>
<div class="pan"></div>
</div>
</body>
<script>
// 获取元素
var item = document.getElementById('item');
var dpan = item.querySelector('.dpan');
var btn = dpan.querySelector('button');
var pan = item.querySelector('.pan');
//点击按钮关闭
btn.onclick = function () {
item.style.display = 'none'
}
//给dpan添加鼠标按下鼠标按下触发事件
dpan.onmousedown = function (e) {
//获取鼠标在dpan内部的坐标
/**
* 如何计算鼠标在盒子内部的距离
* 父元素距离文档左上角的距离减去鼠标在页面的位置,就得到鼠标在盒子内部的距离
* 鼠标在盒子内部的位置=鼠标在页面上的位置-盒子的位置
*/
//事件对象兼容
var e = e || window.event;
//上边距
var l = e.pageX - item.offsetLeft;
//下边距
var t = e.pageY - item.offsetTop;
//鼠标移动事件 给dpan添加鼠标移动事件
dpan.onmousemove = function (e) {
// 鼠标移动过程中,可以计算 item 的 left 和 top
var nLeft = e.pageX - l;
var nTop = e.pageY - t;
//获取的值赋给item 注意必须加上px的单位
item.style.left = nLeft + 'px';
item.style.top = nTop + 'px';
}
}
//鼠标弹起来
dpan.onmouseup = function () {
dpan.onmousemove = null;
};
</script>
</html>
制作思路
- 先获取所有的元素
- 给元素添加鼠标按下事件
- 定义两个变量接收鼠标按下是获取的坐标,存到变量里
- 添加鼠标移动事件
- 在移动的过程中获取box的位置信息
- 将值赋给父盒子,实现跟随鼠标移动
- 添加鼠标弹起事件