元素：mouseleave 事件
================

**`mouseleave`** 事件在定点设备（通常是鼠标）的指针移出某个元素时被触发。

`mouseleave` 和 `mouseout` 是相似的，但是两者的不同在于 `mouseleave` 不会冒泡而 `mouseout` 会冒泡。这意味着当指针离开元素*及*其所有后代时，会触发 `mouseleave`，而当指针离开元素*或*离开元素的后代（即使指针仍在元素内）时，会触发 `mouseout`。

语法
--

在类似 `addEventListener()` 这样的方法中使用事件名称，或设置事件处理器属性。


```js
addEventListener("mouseleave", (event) => {});

onmouseleave = (event) => {};
```

事件类型
----

`MouseEvent`，继承自 `Event`。

Event

UIEvent

MouseEvent事件属性
----

*此接口也从其父接口 `UIEvent` 和 `Event` 继承属性。*

`MouseEvent.altKey` 只读 

在鼠标事件触发时，如果 `alt` 键被按下，则返回 `true`。

`MouseEvent.button` 只读 

在鼠标事件触发时，按下的按钮编号（如果适用）。

`MouseEvent.buttons` 只读 

在鼠标事件触发时，按下的按钮。

`MouseEvent.clientX` 只读 

鼠标指针在本地（DOM 内容）坐标系中的 X 坐标。

`MouseEvent.clientY` 只读 

鼠标指针在本地（DOM 内容）坐标系中的 Y 坐标。

`MouseEvent.ctrlKey` 只读 

在鼠标事件触发时，如果 `control` 键被按下，则返回 `true`。

`MouseEvent.layerX` (en-US) 
非标准
 只读 

返回与事件相对于当前图层的水平坐标。

`MouseEvent.layerY` (en-US) 
非标准
 只读 

返回与事件相对于当前图层的垂直坐标。

`MouseEvent.metaKey` 只读 

在鼠标事件触发时，如果 `meta` 键被按下，则返回 `true`。

`MouseEvent.movementX` 只读 

鼠标指针相对于上一次 `mousemove` 事件的 X 坐标。

`MouseEvent.movementY` 只读 

鼠标指针相对于上一次 `mousemove` 事件的 Y 坐标。

`MouseEvent.offsetX` 只读 

鼠标指针相对于目标节点的内填充边的 X 坐标。

`MouseEvent.offsetY` 只读 

鼠标指针相对于目标节点的内填充边的 Y 坐标。

`MouseEvent.pageX` 只读 

鼠标指针相对于整个文档的 X 坐标。

`MouseEvent.pageY` 只读 

鼠标指针相对于整个文档的 Y 坐标。

`MouseEvent.relatedTarget` 只读 

事件的次要目标（如果适用）。

`MouseEvent.screenX` 只读 

鼠标指针在全局（屏幕）坐标系中的 X 坐标。

`MouseEvent.screenY` 只读 

鼠标指针在全局（屏幕）坐标系中的 Y 坐标。

`MouseEvent.shiftKey` 只读 

在鼠标事件触发时，如果 `shift` 键被按下，则返回 `true`。

`MouseEvent.mozInputSource` 
非标准
 只读 

产生该事件的设备类型（`MOZ_SOURCE_*` 常量之一）。例如，你可以确定鼠标事件是由实际的鼠标还是由触摸事件生成的（这可能会影响你判断与事件关联的坐标时的准确度）。

`MouseEvent.webkitForce` (en-US) 
非标准
 只读 

点击时施加的压力量。

`MouseEvent.x` 只读 

`MouseEvent.clientX` 的别名。

`MouseEvent.y` 只读 

`MouseEvent.clientY` 的别名。

### `mouseleave` 事件的行为

![mouseleave 的行为](/zh-CN/docs/Web/API/Element/mouseleave_event/mouseleave.png)

在指针离开层次结构时，`mouseleave` 事件将被发送到层次结构的每一个元素。当指针从文本（Text）移动到最外层的 div 之外的区域时，会有四个事件分别被发送到层次结构的四个元素。

### `mouseout` 事件的行为

![mouseout 的行为](/zh-CN/docs/Web/API/Element/mouseleave_event/mouseout.png)

单个 `mouseout` 事件被发送到 DOM 树中最深的元素，然后其在层次结构中逐层向上冒泡，直至其被事件处理器取消或到达根元素。

示例
--

`mouseout` 文档有一个示例，说明了 `mouseout` 和 `mouseleave` 之间的区别。

### mouseleave

以下示例使用 `mouseenter` 事件，在鼠标进入委派了该事件的 `<div>` 的空间时，改变该元素的边框。然后在列表中添加一条带有 `mouseenter` 和 `mouseleave` 事件编号的记录。

#### HTML


```html
<div id="mouseTarget">
  <ul id="unorderedList">
    <li>还没有事件！</li>
  </ul>
</div>
```


#### CSS

向 `<div>` 添加一些样式，使其更加可视化。


```css
#mouseTarget {
  box-sizing: border-box;
  width: 15rem;
  border: 1px solid #333;
}
```


#### JavaScript


```js
let enterEventCount = 0;
let leaveEventCount = 0;
const mouseTarget = document.getElementById("mouseTarget");
const unorderedList = document.getElementById("unorderedList");

mouseTarget.addEventListener("mouseenter", (e) => {
  mouseTarget.style.border = "5px dotted orange";
  enterEventCount++;
  addListItem(`这是 mouseenter 事件 ${enterEventCount}.`);
});

mouseTarget.addEventListener("mouseleave", (e) => {
  mouseTarget.style.border = "1px solid #333";
  leaveEventCount++;
  addListItem(`这是 mouseleave 事件 ${leaveEventCount}.`);
});

function addListItem(text) {
  // 使用提供的文本创建一个新的文本节点
  const newTextNode = document.createTextNode(text);

  // 创建一个新的 li 元素
  const newListItem = document.createElement("li");

  // 将文本节点添加到 li 元素中
  newListItem.appendChild(newTextNode);

  // 将新创建的列表元素添加到列表中
  unorderedList.appendChild(newListItem);
}
```


#### 结果

规范
--

| Specification |
| --- |
| UI Events # event-type-mouseleave |
| HTML Standard # handler-onmouseleave |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 事件介绍
* `mousedown`
* `mouseup`
* `mousemove`
* `click`
* `dblclick`
* `mouseover`
* `mouseout`
* `mouseenter`
* `mouseleave`
* `contextmenu`