经纬志
首页 / Leaflet / API 文档

Evented

先看结论

Leaflet 所有事件能力的基类:地图、图层、控件都从它继承,也可以拿它给普通对象加事件。

最后验证 2026-11-03 · Leaflet 1.9.4 · 更新 2026-10-29 · 引用本文
L.Evented.extend(props) → Evented 子类

直接实例化也可以:var bus = new L.Evented();。事件回调收到的对象至少有 type 与 target。

方法

方法返回说明
on(types, fn, context?)this绑定事件,多个类型用空格分隔
off(types?, fn?, context?)this解绑;不传参数时清掉全部监听
once(types, fn, context?)this只触发一次,触发后自动解绑
fire(type, data?, propagate?)this触发事件;propagate 为真时向事件父级冒泡
listens(type, propagate?)boolean是否有该类型的监听器
addEventParent(obj)this设置事件父级,事件可向上冒泡
removeEventParent(obj)this移除事件父级
addEventListener / removeEventListenerthison 与 off 的别名

给普通对象加事件

var Selection = L.Evented.extend({
  select: function (id) {
    this.selectedId = id;
    this.fire('select', { id: id });
  }
});

var selection = new Selection();

selection.on('select', function (e) {
  console.log('选中', e.id, '来自', e.target === selection);
});

selection.once('select', function () {
  console.log('只执行一次');
});

selection.select(12);
selection.select(13);

e.target 指向触发者,e.type 是事件名。 同一类型上的多个监听器按注册顺序依次执行,一个监听器抛错会影响后面的监听器, 回调里需要容错时自己包一层 try。

事件冒泡

图层默认把自己的事件冒泡给地图,map.on('click', fn) 因此能收到要素上的点击。 自定义对象要冒泡,先把目标设为事件父级:

var layerBus = new L.Evented();

layerBus.addEventParent(map);

layerBus.fire('status', { ready: true }, true);

map.on('status', function (e) {
  console.log('收到子级事件', e.ready);
});

fire 的第三个参数不传时不会冒泡。 地图内部的交互事件由 L.Map 自己派发,不依赖这条路径。

解绑要带上函数引用

off('select') 会移除该类型上的全部监听。 只想撤掉自己注册的那一个时,把同一个函数引用传进去: off('select', handler)。 匿名函数没有引用,注册之后就再也无法单独解绑,组件卸载时容易留下闭包引用。

与 DOM 事件的区别

对比项L.Evented原生 DOM 事件
事件对象普通对象,含 type、target、自定义字段MouseEvent 等原生对象
坐标图层事件带 latlng、layerPoint、containerPoint只有 clientX / clientY
冒泡显式 addEventParent 后才会向上沿 DOM 树自动冒泡
绑定工具on / offL.DomEvent.on / off

off() 不带参数会清空全部监听。 在组件卸载时这很方便,但如果对象与他人共享(例如全局事件总线), 会把别人的监听一并删掉。共享对象上始终按类型解绑。

引用本文

经纬志(2026)。《Evented》。https://www.jingweizhi.com/leaflet/api/evented.html(访问日期 2026-11-03)。