Open wuxianqiang opened 4 years ago
先写一个事件代理的方法,这个delegate方法可以给子元素添加和移除绑定事件处理函数。
<body> <div> <ul id="app"> <li class="childClassname">11</li> <li class="childClassname">11</li> </ul> </div> <script> let parentElement = document.getElementById('app') function callback (e) { console.log('ok', e) } delegate(parentElement).on('childClassname', 'click', callback); delegate(parentElement).off('childClassname', 'click', callback); function delegate (parentElement) { function on (childClassname, eventType, listener) { let list = parentElement.getElementsByClassName(childClassname) Array.from(list, (dom) => { let eventStore = dom.eventStore || (dom.eventStore = {}) eventStore[eventType] = listener; }) document.addEventListener(eventType, dispatchEvent, false) } function dispatchEvent (event) { let { type, target } = event let eventType = type; while (target) { let { eventStore } = target; let listener = eventStore && eventStore[eventType] if (listener) { listener.call(target, event) } target = target.parentNode; } } function off (childClassname, eventType, listener) { let list = parentElement.getElementsByClassName(childClassname) Array.from(list, (dom) => { let eventStore = dom.eventStore let listener = eventStore && eventStore[eventType] if (listener) { eventStore[eventType] = null } }) } return {on, off} } </script> </body>
现在你已经明白了如何将子元素绑定的事件都代理到document对象,下面继续深入学习react的绑定事件。
let onClick = () => { console.log('hello') } let element = React.createElement( 'button', { id: 'sayHello', onClick }, 'say', React.createElement('span', { color: 'red' }, 'hello'))
React在渲染DOM的时候会做事件绑定。
function addEvent(dom, eventType, listener) { eventType = eventType.toLowerCase() // 给绑定DOM的节点挂载一个对象 let eventStore = dom.eventStore || (dom.eventStore = {}); // 对象上保存事件名称和事件处理函数{onclick: listener} eventStore[eventType] = listener document.addEventListener(eventType.slice(2), dispatchEvent, false) }
let syntheticEvent; function dispatchEvent(event) { // 此时event是原生事件对象 let { target, type } = event; // 在事件对象中获取事件源和事件名 let eventType = 'on' + type; // 获取合成事件对象 syntheticEvent = getSyntheticEvent(event) while (target) { let { eventStore } = target; let listener = eventStore && eventStore[eventType] if (listener) { listener.call(target, syntheticEvent) } target = target.parentNode; } // 合成事件用完会清空,如果不想清空需要使用persist函数 for (let key in syntheticEvent) { if (key != 'persist') { syntheticEvent[key] = null } } }
function persist() { syntheticEvent = {persist} } function getSyntheticEvent(nativeEvent) { if (!syntheticEvent) { syntheticEvent = {persist} } syntheticEvent.nativeEvent = nativeEvent; syntheticEvent.currentTarget = nativeEvent.target; // 把原生事件对象的属性和方法都复制到合成事件对象中 for (let key in nativeEvent) { if (typeof nativeEvent[key] === 'function') { syntheticEvent[key] = nativeEvent[key].bind(nativeEvent) } else { syntheticEvent[key] = nativeEvent[key] } } return syntheticEvent }
开始使用
let app = document.getElementById('app') function callback (e) { e.persist() console.log('ok', e) } addEvent(app, 'onClick', callback)
完整代码
<script> let app = document.getElementById('app') function callback (e) { e.persist() console.log('ok', e) } addEvent(app, 'onClick', callback) function addEvent(dom, eventType, listener) { eventType = eventType.toLowerCase() // 给绑定DOM的节点挂载一个对象 let eventStore = dom.eventStore || (dom.eventStore = {}); // 对象上保存事件名称和事件处理函数{onclick: listener} eventStore[eventType] = listener document.addEventListener(eventType.slice(2), dispatchEvent, false) } let syntheticEvent; function dispatchEvent(event) { // 此时event是原生事件对象 let { target, type } = event; // 在事件对象中获取事件源和事件名 let eventType = 'on' + type; // 获取合成事件对象 syntheticEvent = getSyntheticEvent(event) while (target) { // 从事件源开始冒泡 let { eventStore } = target; let listener = eventStore && eventStore[eventType] if (listener) { listener.call(target, syntheticEvent) } target = target.parentNode; } // 完成之后清空syntheticEvent for (let key in syntheticEvent) { if (key != 'persist') { syntheticEvent[key] = null } } } function persist() { syntheticEvent = {persist} } function getSyntheticEvent(nativeEvent) { if (!syntheticEvent) { syntheticEvent = {persist} } syntheticEvent.nativeEvent = nativeEvent; syntheticEvent.currentTarget = nativeEvent.target; // 把原生事件对象的属性和方法都复制到合成事件对象中 for (let key in nativeEvent) { if (typeof nativeEvent[key] === 'function') { syntheticEvent[key] = nativeEvent[key].bind(nativeEvent) } else { syntheticEvent[key] = nativeEvent[key] } } return syntheticEvent } </script> </body>
持久化之后下次会创建一个新的对象,旧的对象也不会销毁,两个对象互不干扰 关于persist可以参考官方文档链接
先写一个事件代理的方法,这个delegate方法可以给子元素添加和移除绑定事件处理函数。
现在你已经明白了如何将子元素绑定的事件都代理到document对象,下面继续深入学习react的绑定事件。
React在渲染DOM的时候会做事件绑定。
开始使用
完整代码
持久化之后下次会创建一个新的对象,旧的对象也不会销毁,两个对象互不干扰 关于persist可以参考官方文档链接