Skip to content

属性/事件(鼠标键盘) ​

元素 ​

1. 基础标识与内容属性 ​

属性说明
id元素的唯一标识符
className元素的 class 属性值(字符串形式)
classListDOMTokenList 对象,提供 add/remove/toggle/contains 等方法操作类名
tagName / nodeName标签名称(大写,如 "DIV")
innerHTML元素内部的 HTML 内容(包含标签)
outerHTML元素自身及其内部的完整 HTML
textContent元素及其后代的纯文本内容(不包含 HTML 标签)
innerText类似 textContent,但会考虑 CSS 样式(如 display:none 的内容不会被获取)

2. 尺寸与位置属性(几何信息) ​

属性说明
offsetWidth / offsetHeight元素可见区域的宽高(含 border + padding + scrollbar)
clientWidth / clientHeight内容区域宽高(含 padding,不含 border 和 scrollbar)
scrollWidth / scrollHeight元素内容的实际总宽高(包括溢出不可见的部分)
offsetTop / offsetLeft相对于 offsetParent 的偏移距离
clientTop / clientLeft边框宽度(上/左边框)
scrollTop / scrollLeft元素滚动条滚动的距离
getBoundingClientRect()方法,返回相对于视口的精确位置对象 {top, right, bottom, left, width, height, x, y}

可视窗口

ts
const vw = document.documentElement.clientWidth;  // 可视窗口宽度
const vh = document.documentElement.clientHeight; // 可视窗口高度

3. 节点关系属性(DOM 树遍历) ​

属性说明
parentNode / parentElement父节点 / 父元素节点
childNodes / children所有子节点(含文本/注释) / 仅子元素节点
firstChild / firstElementChild第一个子节点 / 第一个子元素
lastChild / lastElementChild最后一个子节点 / 最后一个子元素
nextSibling / nextElementSibling下一个兄弟节点 / 下一个兄弟元素
previousSibling / previousElementSibling上一个兄弟节点 / 上一个兄弟元素

4. 通用属性访问方法 ​

ts
/* 设置自定义属性 */
元素.setAttribute((属性名), (属性值))

// 设置属性值
element.setAttribute('data-custom', 'value')

// 获取属性值
element.getAttribute('data-custom')

// 判断属性是否存在
element.hasAttribute('disabled')

// 移除属性
element.removeAttribute('class')

推荐替代方案: 对于 data-* 自定义属性,优先使用 dataset API,语法更简洁且自动处理驼峰转换:

ts
// 设置(自动转为 data-user-id)
element.dataset.userId = '123';

// 读取
console.log(element.dataset.userId); // "123"

⚠️ 注意: setAttribute 的值始终是字符串。如果传入数字或对象,会被隐式转换为字符串。而 dataset 赋值同样也是字符串类型。

5. 插入dom元素 ​

创建与克隆 ​

方法说明
document.createElement(tag)创建元素节点
document.createTextNode(text)创建文本节点
document.createDocumentFragment()创建文档片段(内存中的临时容器,批量操作减少重排)
node.cloneNode(deep)克隆节点,deep=true 时递归克隆所有后代

插入与追加 ​

传统方法

方法说明
parent.appendChild(node)追加为最后一个子节点
parent.insertBefore(new, ref)在参考节点之前插入

现代方法

方法调用对象说明
append(...nodes)父元素末尾追加(支持多节点+字符串)
prepend(...nodes)父元素开头插入(支持多节点+字符串)
before(...nodes)参考节点在参考节点之前插入
after(...nodes)参考节点在参考节点之后插入

创建 + 批量插入:高性能渲染列表

ts
// ✅ 使用 DocumentFragment 避免多次重排
const fragment = document.createDocumentFragment();

['西瓜', '葡萄', '芒果'].forEach(text => {
  const li = document.createElement('li');
  li.className = 'item';
  li.textContent = text;
  fragment.appendChild(li);
});

// 一次性插入到末尾(只触发 1 次重排)
document.querySelector('#list').append(fragment);

// 💡 现代写法:before/after/prepend 支持混合传入节点和字符串
const ref = document.querySelector('.item'); // 苹果
ref.before('🍉 ', document.createElement('br')); // 在"苹果"前插入文本+换行

替换与移除 ​

方法说明
parent.replaceChild(new, old)传统替换子节点
oldNode.replaceWith(...nodes)✅ 现代写法,用新节点替换自身
parent.removeChild(node)传统移除子节点
node.remove()✅ 现代写法,直接移除自身

替换与移除:简洁的现代写法

ts
const oldLi = document.querySelectorAll('.item')[1]; // 香蕉

// ✅ 现代:直接替换自身
oldLi.replaceWith(Object.assign(document.createElement('li'), {
  className: 'item',
  textContent: '🍌 新香蕉'
}));

// ✅ 现代:直接移除自身(不需要找父元素)
document.querySelector('.item:last-child').remove();

// ❌ 传统写法对比(繁琐)
// parent.replaceChild(newNode, oldNode);
// parent.removeChild(node);
ts
const el = document.querySelector('#list');

// 相对于视口的精确位置(弹窗定位、吸顶判断必备)
const rect = el.getBoundingClientRect();
console.log(rect.top, rect.left, rect.width, rect.height);

// 插入dom节点
ul.children[0].before(li);  // 在第一个子元素之前插入
ul.prepend(li);             // 插入到最前面
ul.append(li);              // 插入到最后面
li.after(newLi);            // 在 li 之后插入

6. 类名操作 (classList) ​

方法说明
classList.add(...classes)添加一个或多个类
classList.remove(...classes)移除一个或多个类
classList.toggle(class, force?)切换类(有则删,无则加;force 可强制加/删)
classList.contains(class)判断是否包含某个类
classList.replace(old, new)替换类名
classList.entries() / forEach()遍历所有类名

类名操作:告别字符串拼接

ts
const el = document.querySelector('.item');

el.classList.add('active', 'highlight');     // 同时加多个类
el.classList.remove('active');               // 移除
el.classList.toggle('open');                 // 有则删,无则加
el.classList.toggle('disabled', false);      // 第二个参数强制控制:false=删除,true=添加
el.classList.contains('highlight');          // → true
el.classList.replace('highlight', 'selected'); // 替换类名

// 遍历所有类名
el.classList.forEach(cls => console.log(cls));

7. 修改CSS变量、属性值 ​

setProperty?

document.documentElement.style.setProperty() 用于在 <html> 元素上设置 CSS 自定义属性(CSS Variables)或普通内联样式。它是操作全局 CSS 变量最标准的方式。

  • 基本语法
js
element.style.setProperty(propertyName, value, priority);
  • 属性
参数说明示例
propertyNameCSS 属性名(字符串),自定义属性需带 -- 前缀'--theme-color', 'font-size'
value属性值(字符串)'#ff6600', '16px'
priority可选,优先级'important' 或 ''(默认)

常见用法示例

js
const root = document.documentElement;

// ✅ 设置 CSS 自定义属性(最常用)
root.style.setProperty('--primary-color', '#3498db');
root.style.setProperty('--spacing-unit', '8px');

// ✅ 设置带 !important
root.style.setProperty('--danger-color', 'red', 'important');

// ✅ 读取自定义属性(注意:用 getPropertyValue,不是 getProperty)
const color = root.style.getPropertyValue('--primary-color').trim();

// ✅ 删除自定义属性
root.style.removeProperty('--primary-color');
  • 简单示例
js
// 如:css变量--vt-old-z: 1; 使用:z-index: var(--vt-old-z, 888);

// 修改 CSS 变量
document.documentElement.style.setProperty('--vt-old-z', '9999');

// 移除该变量,下次读取时就会触发 888
document.documentElement.style.removeProperty('--vt-new-z');

// 或者显式设为 unset,为默认值
document.documentElement.style.setProperty('--vt-new-z', 'unset');

window ​

ts
1. 获取滚动条滚动的距离
 1). document.documentElement.scrollTop || document.body.scrollTop 或 document.querySelector("div").scrollTop
 2). window.pageYoffset  ---> Y轴滚动条
 3). window.pageXoffset  ---> X轴滚动条
2. window.close() --- 关闭当前页面

滚动到某一区域 ​

scrollTo()

window.scrollTo() 是浏览器原生 API,用于将窗口或可滚动元素滚动到指定位置;

当然,scrollTo 不只是 window 的专利,任何有滚动条的元素都能用;

属性类型默认值说明
topnumber0smooth=平滑动画,instant=瞬间跳转,auto=跟随CSS设置
leftnumber0垂直方向:元素顶部/居中/底部/最近边缘 对齐容器对应位置
behavior'auto' | 'smooth' | 'instant'autosmooth=平滑动画,instant=瞬间跳转,auto=跟随CSS设置

window窗口使用:

ts
window.scrollTo({
  top: 500,        // 垂直滚动位置(px)
  left: 0,         // 水平滚动位置(px),可省略
  behavior: 'smooth' // 'auto'(默认,瞬间跳转) | 'smooth'(平滑动画)
});

dom元素使用:

ts
// 滚动到指定元素的位置(替代 scrollIntoView)
// 当你需要更精确的控制(比如加偏移量)时:
const target = document.querySelector('#section');
const offset = 80; // 例如固定导航栏高度

window.scrollTo({
  top: target.getBoundingClientRect().top + window.scrollY - offset,
  behavior: 'smooth'
});

控制dom元素滚动到可视区域 ​

ts
element.scrollIntoView({ // element 【dom元素】
  behavior: 'smooth',    // 滚动行为
  block: 'start',        // 垂直对齐方式
  inline: 'nearest'      // 水平对齐方式
});

提示

scrollIntoView() 是一个 DOM 元素方法,它的作用非常直接:自动滚动页面或容器,让调用它的元素出现在可视区域内。

scrollIntoView() 只能在 DOM 元素(即 Element 节点)上调用!

属性可选值说明
behavior'auto' | 'smooth' | 'instant'smooth=平滑动画,instant=瞬间跳转,auto=跟随CSS设置
block'start' | 'center' | 'end' | 'nearest'垂直方向:元素顶部/居中/底部/最近边缘 对齐容器对应位置
inline'start' | 'center' | 'end' | 'nearest'水平方向:同上

鼠标 ​

核心鼠标事件类型 ​

事件类型触发时机常用场景
点击类
dblclick鼠标左键双击触发双击编辑、文件打开
mousedown鼠标任意按键按下时触发(左 / 中 / 右)拖拽开始、按住操作
mouseup鼠标任意按键松开时触发(左 / 中 / 右)拖拽结束、释放操作
contextmenu鼠标右键单击(触发上下文菜单)自定义右键菜单
移动类
mousemove鼠标在元素内移动时持续触发拖拽跟踪、鼠标位置监听
mouseover鼠标移入元素(含子元素)时触发悬浮提示(会冒泡)
mouseenter鼠标移入元素(不含子元素)时触发悬浮样式(不冒泡,推荐)
mouseout鼠标移出元素(含子元素)时触发悬浮恢复(会冒泡)
mouseleave鼠标移出元素(不含子元素)时触发悬浮恢复(不冒泡,推荐)
滚动类
wheel鼠标滚轮滚动时触发(上下 / 左右)自定义滚动逻辑、防滚动穿透
其他
drag元素被拖拽时持续触发拖拽过程跟踪
dragstart元素开始被拖拽时触发拖拽初始化
dragend元素拖拽结束时触发拖拽收尾
drop拖拽元素释放到目标元素时触发拖拽放置逻辑

🔑 关键区别

mouseenter/mouseleave 不冒泡;

mouseover/mouseout 会冒泡(子元素触发会传递到父元素)

因此做悬浮交互时优先用 mouseenter/mouseleave。

鼠标事件对象核心属性 ​

属性作用
e.clientX/e.clientY鼠标相对于可视窗口的坐标(不含滚动条偏移)
e.pageX/e.pageY鼠标相对于文档的坐标(含滚动条偏移,常用)
e.screenX/e.screenY鼠标相对于电脑屏幕的坐标
e.offsetX/e.offsetY鼠标相对于触发元素的内部坐标(元素左上角为 0)
e.button按下的鼠标按键:0 = 左键,1 = 中键,2 = 右键(mousedown/mouseup 有效)
e.ctrlKey/e.shiftKey/e.altKey按下按键时是否按住 Ctrl/Shift/Alt 键(组合操作)
e.target触发事件的原始元素(事件冒泡时不变)
e.currentTarget绑定事件的当前元素(事件冒泡时为当前处理元素)
e.preventDefault()阻止默认行为(如右键菜单、链接跳转)
e.stopPropagation()阻止事件冒泡(如子元素点击不触发父元素事件)

常见示例 ​

获取鼠标位置 ​

vue
<template>
<div id="box" style="width: 300px; height: 200px; border: 1px solid #000;"></div>
<p id="pos"></p>
</template>

<script>
  const box = document.getElementById('box');
  const pos = document.getElementById('pos');
  
  box.addEventListener('mousemove', (e) => {
    pos.innerHTML = `
      相对于文档:${e.pageX}, ${e.pageY}<br>
      相对于元素:${e.offsetX}, ${e.offsetY}<br>
      相对于窗口:${e.clientX}, ${e.clientY}
    `;
  });
</script>

自定义右键菜单 ​

vue
<template>
<div id="customMenu" style="display: none; position: absolute; width: 120px; background: #fff; border: 1px solid #ccc; padding: 5px;">
  <div>复制</div>
  <div>粘贴</div>
  <div>删除</div>
</div>
</template>

<script>
  const menu = document.getElementById('customMenu');
  
  // 禁用默认右键菜单
  document.addEventListener('contextmenu', (e) => {
    e.preventDefault();
    // 定位自定义菜单到鼠标位置
    menu.style.left = `${e.pageX}px`;
    menu.style.top = `${e.pageY}px`;
    menu.style.display = 'block';
  });
  
  // 点击空白处关闭菜单
  document.addEventListener('click', () => {
    menu.style.display = 'none';
  });
</script>

鼠标拖拽元素 ​

核心

mousedown 记录初始位置 → mousemove 计算偏移 → mouseup 停止监听

vue
<template>
<div id="dragBox" style="width: 100px; height: 100px; background: red; position: absolute; cursor: move;"></div>
</template>

<script>
  const dragBox = document.getElementById('dragBox');
  let isDragging = false;
  let startX, startY;

  // 按下鼠标:开始拖拽
  dragBox.addEventListener('mousedown', (e) => {
    isDragging = true;
    // 记录鼠标相对于元素的初始位置
    startX = e.offsetX;
    startY = e.offsetY;
    dragBox.style.opacity = '0.8'; // 视觉反馈
  });

  // 移动鼠标:更新位置(绑定到document,避免鼠标移出元素中断)
  document.addEventListener('mousemove', (e) => {
    if (!isDragging) return;
    // 计算元素新位置:鼠标文档坐标 - 初始偏移
    const x = e.pageX - startX;
    const y = e.pageY - startY;
    dragBox.style.left = `${x}px`;
    dragBox.style.top = `${y}px`;
  });

  // 松开鼠标:结束拖拽
  document.addEventListener('mouseup', () => {
    if (isDragging) {
      isDragging = false;
      dragBox.style.opacity = '1';
    }
  });
</script>

监听鼠标滚轮方向 ​

ts
/* 鼠标滚轮事件 */
window.onwheel = (e) => {
    if(e.wheelDeltaY > 0){
        console.log("往上滚动");
    } else {
        console.log("往下滚动");
    }
}

--------- 或 ---------

document.addEventListener('wheel', (e) => {
  // e.deltaY > 0 向下滚动,< 0 向上滚动
  if (e.deltaY > 0) {
    console.log('滚轮向下');
  } else {
    console.log('滚轮向上');
  }
  // 阻止默认滚动(如页面不跟随滚轮滚动)
  // e.preventDefault();
});

区分左键 / 右键 / 中键点击 ​

ts
document.addEventListener('mousedown', (e) => {
  switch(e.button) {
    case 0:
      console.log('左键按下');
      break;
    case 1:
      console.log('中键按下(滚轮点击)');
      break;
    case 2:
      console.log('右键按下');
      break;
  }
});

注意事项 ​

事件冒泡 ​

提示

click、mousedown 等事件会冒泡到父元素,如需阻止可调用 e.stopPropagation()。

ts
// 示例:子元素点击不触发父元素事件
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('click', () => console.log('父元素点击'));
child.addEventListener('click', (e) => {
  e.stopPropagation(); // 阻止冒泡
  console.log('子元素点击');
});

拖拽事件的兼容性 ​

提示

原生拖拽(drag/drop)需给元素设置 draggable="true",且 drop 事件触发前需阻止 dragover 的默认行为:

ts
const dropTarget = document.getElementById('dropTarget');
dropTarget.addEventListener('dragover', (e) => {
  e.preventDefault(); // 必须阻止默认行为,否则drop不触发
});
dropTarget.addEventListener('drop', (e) => {
  console.log('元素拖入目标');
});

鼠标位置的兼容性 ​

提示

pageX/pageY 在 IE 低版本中需兼容(可通过 clientX + document.documentElement.scrollLeft 计算)。

ts
let timer = null;
document.addEventListener('mousemove', (e) => {
  if (timer) clearTimeout(timer);
  timer = setTimeout(() => {
    // 执行复杂逻辑(如更新DOM)
    console.log('鼠标位置:', e.pageX, e.pageY);
  }, 16); // 约60帧/秒
});

性能优化 ​

提示

mousemove 触发频率极高,如需复杂逻辑,可通过「节流」减少触发次数

ts
let timer = null;
document.addEventListener('mousemove', (e) => {
  if (timer) clearTimeout(timer);
  timer = setTimeout(() => {
    // 执行复杂逻辑(如更新DOM)
    console.log('鼠标位置:', e.pageX, e.pageY);
  }, 16); // 约60帧/秒
});

键盘 ​

ts
// 方式1:addEventListener(推荐,支持多事件绑定)
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);

// 方式2:直接赋值(仅能绑定一个事件)
// document.onkeydown = handleKeyDown;

// 事件处理函数
function handleKeyDown(e) {
  console.log('按键按下:', {
    key: e.key,        // 按键名称(如 'a'、'Enter'、'ArrowUp')
    code: e.code,      // 按键编码(如 'KeyA'、'Enter'、'ArrowUp')
    keyCode: e.keyCode,// 按键ASCII码(已废弃,如 65 对应 A,13 对应 Enter)
    altKey: e.altKey,  // 是否按住 Alt
    ctrlKey: e.ctrlKey,// 是否按住 Ctrl
    shiftKey: e.shiftKey,// 是否按住 Shift
    metaKey: e.metaKey // 是否按住 Windows/Command 键
  });

  // 阻止默认行为(如禁用回车提交表单、禁用方向键滚动)
  // e.preventDefault();
}

function handleKeyUp(e) {
  console.log('按键松开:', e.key);
}

// 移除事件监听(需保留函数引用)
// document.removeEventListener('keydown', handleKeyDown);

表单 ​

ts
监听滚动条移动事件 ---> scroll
获取焦点 ---> focus
失去焦点 ---> blur
监听表单值发生变化 ---> change

Copyright © 2026 Luke