1、点击事件获取的信息:
①offsetX,offsetY 元素坐标系
点击位置到所在的dom元素的外边框的距离
②offsetTop,offsetLeft
点击位置所在dom元素的left和top
③clientX,clientY 浏览器坐标系
点击位置到浏览器视口的坐标(不会计算滚动条)
④pageX,pageY 文档坐标系
点击位置到document的边界的坐标(会计算滚动条距离)
⑤screenX,screenY 显示器坐标系
点击位置到屏幕边界的坐标
2、拖拽事件
js原生实现拖拽原理:
mouseDown -》mounseover移入 -》 mousemove移动 -》mouseEnter移出
通过点击开始拖动和释放结束拖动两个事件能获取的信息,计算出dom变化后的left和top,并且修改。
·点击时记录offsetX,offsetY(当前点击位置到达拖动的dom的外边框的距离)
松手时记录此时的pageX,pageY。然后把此时的pageX - 刚刚记录的offsetX,得到移动后的left。top同理。
·html5拖拽:
①dragstart:鼠标点击并且开始拖动(相当于mousedown+mousemove的组合),此时这个拖动元素会触发该事件。
②dragenter:鼠标正在拖动元素,并且鼠标进入某个dom(目标元素) ,此时这个dom会触发该事件。
③dragover:鼠标在其它dom元素(目标元素)身上移动,此时这个dom会频繁触发该事件。
④dragleave:鼠标正在拖动元素,并且鼠标移出某个dom(目标元素),此时这个dom会触发该事件。
⑤drop:正拖拽元素,并且松开鼠标
⑥drag:拖动过程中,被拖动的元素频繁触发
⑦dragend:拖动结束后,被拖动的元素触发
加粗的是被拖动元素的事件。没加粗的是目标元素的事件。
drop之前一定会有dragover,所以通常用dragover保护drop。并且在dragover中需要移除默认行为,因为div的浏览器默认行为就是不允许drop的。
e.dataTransfer对象
用于装载移动资源,在dragstart的时候进行设置资源,在drop的时候取出。
3、原生实现拖拽排序
<template>
<div
class="wrap"
@dragstart="handleDragStart"
@dragover="handleDragOver"
@dragend="drop"
>
<div class="item" draggable>1</div>
<div class="item" draggable>2</div>
<div class="item" draggable>3</div>
<div class="item" draggable>4</div>
<div class="item" draggable>5</div>
<div class="item" draggable>6</div>
<div class="item" draggable>7</div>
<div class="item" draggable>8</div>
</div>
</template>
<script>
export default {
name: "DragSort",
data: () => {
return {
currentDrag: null,
};
},
mounted() {},
methods: {
drop: (e) => {
e.target.classList.remove("drag");
},
handleDragStart(e) {
this.currentDrag = e.target;
//不然拖拽的样式会生效到拖动元素身上!
setTimeout(() => {
this.currentDrag.classList.add("drag");
}, 50);
},
handleDragOver(e) {
e.preventDefault();
if (
this.currentDrag == e.target ||
!e.target?.classList?.contains("item")
) {
return;
}
const target = e.target;
//获取元素的索引,先把dom的List转化成数组,然后找到对应的两个元素的索引
const list = Array.from(document.querySelector(".wrap").children);
const targetIndex = list.indexOf(target);
const dragIndex = list.indexOf(this.currentDrag);
//交换元素的位置,向上和向下拖拽的逻辑是不同的。根据index判断是向上还是向下
if (targetIndex > dragIndex) {
let wrap = document.querySelector(".wrap");
wrap.insertBefore(this.currentDrag, target.nextSibling);
} else {
let wrap = document.querySelector(".wrap");
wrap.insertBefore(this.currentDrag, target);
}
},
},
};
</script>
<style>
.wrap {
display: grid;
grid-template-columns: 1fr;
margin: 0 auto;
height: 340px;
width: 450px;
border: 1px solid red;
border-radius: 6px;
}
.item {
box-sizing: border-box;
overflow: hidden;
border-radius: 5px;
background-color: pink;
margin-bottom: 5px;
text-align: center;
}
.drag {
border: 1px dashed #000;
background-color: transparent;
}
</style>
4、dom操作
①元素操作
1. 根据 ID 名
document.getElementById()
2. 根据标签名
document.getElementsByTagName() 返回 HTMLCollection 对象
元素对象.getElementsByTagName()
3. 根据类名
document.getElementsByClassName() 返回 HTMLCollection 对象
元素对象.getElementsByClassName()
4. 根据name属性值
document.getElementsByName() 返回 NodeList 对象
5. 使用 CSS 选择器
document.querySelector(); 返回第一个满足条件的元素
document.querySelectorAll() 返回NodeList对象
元素对象.querySelector();
元素对象.querySelectorAll();
6. 获取所有的元素
document.all
② 根据元素关系获取元素(文档关系)
节点树:
childNodes
firstChild
lastChild
parentNode
previousSibling
nextSibling
元素树:
children
firstElementChild
lastElementChild
parentElement
previousElementSibling
nextElementSibling
③ 操作元素的属性
1) 读写内置属性
元素对象.属性名;
元素对象['属性名'];
2) 读写自定义属性(写在标签上的属性)
元素对象.getAttribute('属性名');
元素对象.setAttribute('属性名', '值');
3) 读写data-格式的自定义属性
元素对象.dataset.属性名;
读写行内样式 - style
// 设置行内样式
元素对象.style.color = 'red';
元素对象.style.backgroudColor = 'red';
元素对象.style['background-color'] = 'red';
// 读取行内样式
元素对象.style.color;
元素对象.style.backgroudColor;
元素对象.style['background-color'];
通过设置元素的类名操作样式 - classList
① className
HTML 标签中的 class 属性对应 js 元素对象的 className 属性,是内置属性
元素对象.className; // 可读可写
② classList
classList 是一个包含了该元素所有类名的伪数组,属性和方法如下:
元素对象.classList.length 类名个数
元素对象.classList.add() 添加一个类名
元素对象.classList.remove() 删除一个类名
元素对象.classList.toggle() 切换一个类名(元素有该类名删除,无该类名添加)
3 读写元素的文本内容(可读可写)
元素对象.innerHTML 读写元素内部的HTML内容
元素对象.outerHTML 读写包括本元素在内的HTML内容
元素对象.innerText 读写元素内部的文本内容(去除HTML标签,不保留缩进格式)
元素对象.textContent 读写元素内部的文本内容(去除HTML标签,保留缩进格式)
注意: 只有双标签元素才有可能具有文本内容!
4 读取元素的尺寸(只读)
offsetWidth、offsetHeight 获取元素整体的宽高(内容+内边距+ 边框)
clientWidth、clientHeight 获取元素除去边框外的宽高(内容+内边距)
scrollWidth、scrollHeight client的基础上+溢出部分的宽高 (没有溢出内容同 client系列)
getBoundingClientRect() 返回一个对象,对象中有 width、height 属性,同 offset 系列
注意: 以上方式只能读取元素的宽高,如果要设置元素的宽高用CSS样式设置。
获取视口的宽高:
// 1 方式一
window.innerWidth;
window.innerHeight;
// 2 方式二 与方式一相比,不会把滚动条本身的宽度算进来
document.documentElement.clientWidth;
document.documentElement.clientHeight;
5 读取元素的位置 (只读)
offsetLeft、offsetTop 获取元素在第一个定位的祖先元素上的位置(如果没有定位的祖先元素,参考整个文档)
clientLeft、clientTop 获取左边框宽度、上边框宽度
getBoundingClientRect() 返回一个对象,具有如下属性:
left、top 获取元素左上角在视口中的坐标
x、y 同 left、top
right、bottom 获取元素右边框在视口的位置、下边框在视口位置
注意: 以上方式只能读取元素的位置,如果要设置元素的位置用CSS样式设置。
rectDom.right - rectDom.left === rectDom.width;
rectDom.bottom-rectDom.top === rectDom.height;
6 读写元素中内容的位置(可读可写)
scrollLeft 读取或设置元素中内容的水平位置
scrollTop 读取或设置元素中内容的垂直位置
设置元素中内容的位置,有两个前提:
① 元素中的内容要溢出。
② 元素的 CSS 属性 overflow 不能设置为 visible,可以是 auto、hidden、scroll。
读取或设置页面在视口中的位置:
// 非IE
document.documentElement.scrollLeft
document.documentElement.scrollTop
// IE
document.body.scrollLeft
document.body.scrollTop
// 兼容性获取页面滚动距离的方式
document.documentElement.scrollTop || document.body.scrollTop;