第113天 用js写一个事件侦听器的方法
题面讲得有点迷惑...我瞎猜一下它要我干啥吧
事件监听器:EventListener,就是 EventEmitter 触发事件时的 handler,是一个函数。
然后给这个函数增加一个方法?
这里有一份非常短的 Event Emitter 实现(甚至支持通配符:
class Ev {
e = { '*': [] }
on(n, h) { this.e[n] = (this.e[n] || []).concat(h) }
emit(n, p) { this.e['*'].concat(this.e[n]).map(h => h(p)) }
}
题意不清..先写个。。
class EventBus {
events = {};
on(eventName, callback) {
const events = this.events;
if (!events[eventName]) {
events[eventName] = [];
}
events[eventName].push(callback);
return this;
}
emit(eventName, params) {
const events = this.events;
if (events[eventName]) {
events[eventName].forEach(cb => cb(params));
}
return this;
}
}
题意不清..先写个。。 class EventBus { events = {}; on(eventName, callback) { const events = this.events; if (!events[eventName]) { events[eventName] = []; } events[eventName].push(callback); return this; } emit(eventName, params) { const events = this.events; if (events[eventName]) { events[eventName].forEach(cb => cb(params)); } return this; } }
events = {};这样直接赋值是不对的,需要用构造函数包裹。
constructor() {
this.events = {}
}
@bertcai
events = {};这样直接赋值是不对的,需要用构造函数包裹。constructor() { this.events = {} }
类内直接声明成员是一个 Stage 3 草案;见此。
题意不清..先写个。。 class EventBus { events = {}; on(eventName, callback) { const events = this.events; if (!events[eventName]) { events[eventName] = []; } events[eventName].push(callback); return this; } emit(eventName, params) { const events = this.events; if (events[eventName]) { events[eventName].forEach(cb => cb(params)); } return this; } }
events = {};这样直接赋值是不对的,需要用构造函数包裹。constructor() { this.events = {} }感谢指出..
实际可以这么写的,有babel..我本来写的ts。。删了private 之类的ㄟ( ▔, ▔ )ㄏ
<body>
<div>
<span id="a">点击</span>
<a href="#" id="b">超链接</a>
<button id="d" onclick="remove()">点击移除事件绑定</button>
<button onclick="add()">点击添加事件绑定</button>
</div>
<script>
var eventTool = {
//获取事件 window.event兼容ie
getEvent: function (e) {
return e || window.event
},
//获取事件触发元素 srcElement ie独有
getTarget: function (e) {
return e.target || e.srcElement
},
addListener: function (e, type, hander) {
if (e.addEventListener) {
//兼容ie ie没有事件捕获的说法 因此设为false
//dom2
e.addEventListener(type, hander, false);
} else if (e.attachEvent) {
//IE
e.attachEvent('on' + type, hander)
} else {
//dom0
e['on' + type] = hander
}
},
removeListener: function (e, type, hander) {
if (e.removeEventListener) {
e.removeEventListener(type, hander, false)
} else if (e.detachEvent) {
e.detachEvent('on' + type, hander)
}
else { e['on' + type] = null }
},
//阻止事件冒泡
stopPropagation: function (e) {
if (e.stopPropagation) {
// ie以外阻止冒泡
e.stopPropagation()
}
else {
//ie独有阻止冒泡 新版本的chrome等浏览器也支持
e.cancelBubble = true
}
},
// 阻止事件相关元素的默认事件
preventDefault: function (e) {
if (e.preventDefault) {
e.preventDefault()
}
else {
//ie的阻止默认事件方式
e.returnValue = false;
}
}
}
var btn = document.getElementById('a');
var link = document.getElementById('b');
var fun = function (e) {
var e = eventTool.getEvent(e);
var t = eventTool.getTarget(e);
console.log(e)
console.log(t)
eventTool.stopPropagation(e)
}
var add = function () {
eventTool.addListener(btn, 'click', fun)
eventTool.addListener(link, 'click', fun)
}
var remove = function () {
console.log(btn)
eventTool.removeListener(btn, 'click', fun)
}
</script>
</body>
function addEvent(elem, type, handle) {
if (elem.addEventListener) { //W3C标准
elem.addEventListener(type, handle, false); //事件冒泡时触发
} else if (elem.attachEvent) { //IE独有
elem.attachEvent('on' + type, function() {
handle.call(elem); //改变this使其指向指定元素
});
} else {
elem['on' + type] = handle; // 最古老
}
}
参考网上的代码加了点自己的东西
/**
* 一个简单的发布订阅者模式
*/
interface IHandler {
fn: Function,
type: string,
name: string
}
export default class EventUtils {
/**
* 键值对 对应事件名称以及数组的值
*/
static handler = {}
/**
* on 方法 添加监听事件
*/
static on (name: string, handler: Function): EventUtils {
const i:IHandler = {
fn: handler,
type: 'on',
name: name
}
if (Object.keys(EventUtils.handler).includes(name)) {
EventUtils.handler[name].push(i)
return EventUtils
}
EventUtils.handler[name] = [].concat(i)
return EventUtils
}
/**
* off 方法 移除监听事件
*/
static off (name: string, handler: Function): EventUtils {
const event: any[] = EventUtils.handler[name]
if (event) {
for (let i = event.length - 1; i >= 0; i--) {
if (event[i].fn === handler) {
event.splice(i, 1)
}
}
}
return EventUtils
}
/**
* emit 方法 触发监听的事件
*/
static emit (name: string, ...args: any): EventUtils {
const event = EventUtils.handler[name]
let newEvent = []
event && event.length && event.forEach((item: IHandler, index: number) => {
item.fn.call(this, ...args)
// 如果有只监听一次的事件
if (item.type !== 'once') {
newEvent.push(event.slice(index, index + 1))
}
})
const hasOnce = event && event.length && event.some((item: IHandler) => {
return item.type === 'once'
})
if (hasOnce) {
EventUtils.handler[name] = newEvent
}
// 这里做一个执行完成之后的 once代码 off 的操作
return EventUtils
}
/**
* once 方法 添加事件 只会被执行一次
*/
static once (name: string, handler: Function): void {
EventUtils.on(name, handler)
EventUtils.handler[name][0]['type'] = 'once'
}
}
Most helpful comment