Comparing version 0.0.3 to 0.0.4
@@ -109,2 +109,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
constructor(model) { | ||
this.modelListeners = []; | ||
this.model = model; | ||
@@ -118,7 +119,22 @@ this.initModelEvents(); | ||
const eventType = listener.eventType; | ||
this.model.on(eventType, (...args) => { | ||
const handler = (...args) => { | ||
listener.handler(...args); | ||
}; | ||
this.modelListeners.push({ | ||
eventType, | ||
handler | ||
}); | ||
this.model.on(eventType, handler); | ||
} | ||
} | ||
destroy() { | ||
this.onDestroy(); | ||
for (const modelListener of this.modelListeners) { | ||
this.model.removeListener(modelListener.eventType, modelListener.handler); | ||
} | ||
delete this.model; | ||
} | ||
onDestroy() { | ||
// redefine me | ||
} | ||
} | ||
@@ -231,2 +247,5 @@ exports.Controller = Controller; | ||
class DOMEvents { | ||
constructor() { | ||
this.listeners = []; | ||
} | ||
addController(controller, view) { | ||
@@ -238,2 +257,10 @@ const listeners = ControllerMeta_1.getListeners(controller); | ||
} | ||
destroyListeners(view) { | ||
const viewListeners = this.listeners.filter(listener => listener.view === view); | ||
for (const listener of viewListeners) { | ||
listener.destroy(); | ||
const listenerIndex = this.listeners.indexOf(listener); | ||
this.listeners.splice(listenerIndex, 1); | ||
} | ||
} | ||
addListener(listener, view) { | ||
@@ -251,2 +278,3 @@ if (!ControllerMeta_1.isDomListener(listener)) { | ||
domListener.listen(); | ||
this.listeners.push(domListener); | ||
} | ||
@@ -298,6 +326,14 @@ } | ||
listen() { | ||
document.addEventListener(this.eventType, (event) => { | ||
this.domHandler = (event) => { | ||
this.onDOMEvent(event); | ||
}); | ||
}; | ||
document.addEventListener(this.eventType, this.domHandler); | ||
} | ||
destroy() { | ||
document.removeEventListener(this.eventType, this.domHandler); | ||
delete this.view; | ||
delete this.handler; | ||
delete this.domHandler; | ||
delete this.handlerArgs; | ||
} | ||
onDOMEvent(event) { | ||
@@ -437,2 +473,16 @@ if (this.isValidEvent(event)) { | ||
} | ||
componentWillUnmount() { | ||
// clear memory leaks | ||
this.onDestroy(); | ||
const rootEl = ReactDOM.findDOMNode(this); | ||
delete rootEl._model; | ||
domEvents.destroyListeners(this); | ||
for (const controller of this.controllersInstances) { | ||
controller.destroy(); | ||
} | ||
this.controllersInstances = []; | ||
} | ||
onDestroy() { | ||
// redefine me | ||
} | ||
controllers() { | ||
@@ -439,0 +489,0 @@ return []; |
@@ -1,2 +0,2 @@ | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("ReactDOM"),require("React"),require("EventEmitterModule"));else if("function"==typeof define&&define.amd)define(["ReactDOM","React","EventEmitterModule"],t);else{var n="object"==typeof exports?t(require("ReactDOM"),require("React"),require("EventEmitterModule")):t(e.ReactDOM,e.React,e.EventEmitterModule);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(window,(function(e,t,n){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e,t){return(e.constructor.prototype._handlersArguments||[]).filter(e=>e.methodName===t).sort((e,t)=>e.argumentIndex-t.argumentIndex).map(e=>e.eventPropertyPath)}function o(e){return"change"===e.eventType&&"model"===e.selector}Object.defineProperty(t,"__esModule",{value:!0}),t.isDomListener=t.isModelListener=t.getListeners=t.arg=t.on=void 0,t.on=function(e,t){return(n,r,o)=>{n._listenersMeta||(n._listenersMeta=[]);const i={eventType:e,selector:t,methodName:r};n._listenersMeta.push(i)}},t.arg=function(e,t,...n){return(r,o,i)=>{r._handlersArguments||(r._handlersArguments=[]);const s={methodName:o,argumentIndex:i,eventPropertyPath:[]};if("string"==typeof e){const r=[e];t&&r.push(t),n.length&&r.push(...n),s.eventPropertyPath=r}else{const t=e;s.eventPropertyPath=t}r._handlersArguments.push(s)}},t.getListeners=function(e){const t=e.constructor.prototype._listenersMeta||[],n=[];for(const o of t){const t=e[o.methodName].bind(e),i=r(e,o.methodName),s={eventType:o.eventType,selector:o.selector,handlerArgs:i,handler:t};n.push(s)}return n},t.isModelListener=o,t.isDomListener=function(e){return!o(e)}},function(e,n){e.exports=t},function(e,t){e.exports=n},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.arg=t.on=t.Controller=t.View=t.Model=t.EventEmitter=t.ReactDOM=t.React=void 0;const s=i(n(2));t.React=s;const c=i(n(0));t.ReactDOM=c;const l=n(3);Object.defineProperty(t,"EventEmitter",{enumerable:!0,get:function(){return l.EventEmitter}});const u=n(1);Object.defineProperty(t,"on",{enumerable:!0,get:function(){return u.on}}),Object.defineProperty(t,"arg",{enumerable:!0,get:function(){return u.arg}});const a=n(5);Object.defineProperty(t,"Model",{enumerable:!0,get:function(){return a.Model}});const d=n(6);Object.defineProperty(t,"View",{enumerable:!0,get:function(){return d.View}});const f=n(12);if(Object.defineProperty(t,"Controller",{enumerable:!0,get:function(){return f.Controller}}),"undefined"!=typeof window){const e=window;e.MVC={React:s,ReactDOM:c,EventEmitter:l.EventEmitter,Model:a.Model,View:d.View,Controller:f.Controller,on:u.on,arg:u.arg},e.React||(e.React=s),e.ReactDOM||(e.ReactDOM=c),e.EventEmitter||(e.EventEmitter=l.EventEmitter)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Model=void 0;const r=n(3);class o extends r.EventEmitter{set(e,t={}){const n={};let r=!1;for(const t in e){const o=e[t];o!==this[t]&&(r=!0,this[t]=o,n[t]=o)}r&&this.emit("change",n,t)}on(e,t){return super.on(e,t)}}t.Model=o},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.View=void 0;const s=i(n(2)),c=i(n(0)),l=new(n(7).DOMEvents);class u extends s.Component{constructor(e){super(e),this.initModel(e.model),this.createControllers()}createControllers(){const e=this.controllers();this.controllersInstances=[];for(const t of e){const e=this.createController(t);this.controllersInstances.push(e)}}createController(e){const t=new e(this.model);return l.addController(t,this),t}initModel(e){this.model=e,this.model.on("change",e=>{this.setState({changes:e})})}render(){return this.template(this.model)}componentDidMount(){c.findDOMNode(this)._model=this.model}controllers(){return[]}}t.View=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DOMEvents=void 0;const r=n(8),o=n(1);t.DOMEvents=class{addController(e,t){const n=o.getListeners(e);for(const e of n)this.addListener(e,t)}addListener(e,t){if(!o.isDomListener(e))return;new r.DOMListener({eventType:e.eventType,selector:e.selector,handlerArgs:e.handlerArgs,handler:e.handler,view:t}).listen()}}},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.DOMListener=void 0;const s=i(n(0)),c=n(9),l=n(10),u=n(11);t.DOMListener=class{constructor(e){this.eventType=e.eventType,this.selector=e.selector,this.handlerArgs=e.handlerArgs,this.handler=e.handler,this.view=e.view}listen(){document.addEventListener(this.eventType,e=>{this.onDOMEvent(e)})}onDOMEvent(e){if(this.isValidEvent(e)){const t=this.getHandlerArgs(e);this.handler(...t)}}isValidEvent(e){const t=s.findDOMNode(this.view);return c.isValidTarget({componentEl:t,selector:this.selector,target:e.target})}getHandlerArgs(e){return this.handlerArgs.map(t=>{if("function"==typeof t){const n=t,r=u.getNearestModelByEvent(e,n);if(!r)throw new Error("cannot find model: "+n.name);return r}return l.getPropertyFromEvent(e,t)})}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isValidTarget=void 0,t.isValidTarget=function(e){let t=e.target,n=!1,r=!1;for(;t;){if("."+t.className===e.selector&&(r=!0),t===e.componentEl){n=!0;break}t=t.parentElement}return n&&r}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getPropertyFromEvent=void 0,t.getPropertyFromEvent=function(e,t){let n=e;for(const e of t)n=n[e];return n}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getNearestModelByEvent=void 0,t.getNearestModelByEvent=function(e,t){let n=e.target;for(;n;){const e=n._model;if(e instanceof t)return e;n=n.parentElement}return null}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Controller=void 0;const r=n(1);t.Controller=class{constructor(e){this.model=e,this.initModelEvents()}initModelEvents(){const e=r.getListeners(this).filter(e=>r.isModelListener(e));for(const t of e){const e=t.eventType;this.model.on(e,(...e)=>{t.handler(...e)})}}}}])})); | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("ReactDOM"),require("React"),require("EventEmitterModule"));else if("function"==typeof define&&define.amd)define(["ReactDOM","React","EventEmitterModule"],t);else{var n="object"==typeof exports?t(require("ReactDOM"),require("React"),require("EventEmitterModule")):t(e.ReactDOM,e.React,e.EventEmitterModule);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}(window,(function(e,t,n){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=4)}([function(t,n){t.exports=e},function(e,t,n){"use strict";function r(e,t){return(e.constructor.prototype._handlersArguments||[]).filter(e=>e.methodName===t).sort((e,t)=>e.argumentIndex-t.argumentIndex).map(e=>e.eventPropertyPath)}function o(e){return"change"===e.eventType&&"model"===e.selector}Object.defineProperty(t,"__esModule",{value:!0}),t.isDomListener=t.isModelListener=t.getListeners=t.arg=t.on=void 0,t.on=function(e,t){return(n,r,o)=>{n._listenersMeta||(n._listenersMeta=[]);const s={eventType:e,selector:t,methodName:r};n._listenersMeta.push(s)}},t.arg=function(e,t,...n){return(r,o,s)=>{r._handlersArguments||(r._handlersArguments=[]);const i={methodName:o,argumentIndex:s,eventPropertyPath:[]};if("string"==typeof e){const r=[e];t&&r.push(t),n.length&&r.push(...n),i.eventPropertyPath=r}else{const t=e;i.eventPropertyPath=t}r._handlersArguments.push(i)}},t.getListeners=function(e){const t=e.constructor.prototype._listenersMeta||[],n=[];for(const o of t){const t=e[o.methodName].bind(e),s=r(e,o.methodName),i={eventType:o.eventType,selector:o.selector,handlerArgs:s,handler:t};n.push(i)}return n},t.isModelListener=o,t.isDomListener=function(e){return!o(e)}},function(e,n){e.exports=t},function(e,t){e.exports=n},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.arg=t.on=t.Controller=t.View=t.Model=t.EventEmitter=t.ReactDOM=t.React=void 0;const i=s(n(2));t.React=i;const l=s(n(0));t.ReactDOM=l;const c=n(3);Object.defineProperty(t,"EventEmitter",{enumerable:!0,get:function(){return c.EventEmitter}});const u=n(1);Object.defineProperty(t,"on",{enumerable:!0,get:function(){return u.on}}),Object.defineProperty(t,"arg",{enumerable:!0,get:function(){return u.arg}});const d=n(5);Object.defineProperty(t,"Model",{enumerable:!0,get:function(){return d.Model}});const a=n(6);Object.defineProperty(t,"View",{enumerable:!0,get:function(){return a.View}});const f=n(12);if(Object.defineProperty(t,"Controller",{enumerable:!0,get:function(){return f.Controller}}),"undefined"!=typeof window){const e=window;e.MVC={React:i,ReactDOM:l,EventEmitter:c.EventEmitter,Model:d.Model,View:a.View,Controller:f.Controller,on:u.on,arg:u.arg},e.React||(e.React=i),e.ReactDOM||(e.ReactDOM=l),e.EventEmitter||(e.EventEmitter=c.EventEmitter)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Model=void 0;const r=n(3);class o extends r.EventEmitter{set(e,t={}){const n={};let r=!1;for(const t in e){const o=e[t];o!==this[t]&&(r=!0,this[t]=o,n[t]=o)}r&&this.emit("change",n,t)}on(e,t){return super.on(e,t)}}t.Model=o},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.View=void 0;const i=s(n(2)),l=s(n(0)),c=new(n(7).DOMEvents);class u extends i.Component{constructor(e){super(e),this.initModel(e.model),this.createControllers()}createControllers(){const e=this.controllers();this.controllersInstances=[];for(const t of e){const e=this.createController(t);this.controllersInstances.push(e)}}createController(e){const t=new e(this.model);return c.addController(t,this),t}initModel(e){this.model=e,this.model.on("change",e=>{this.setState({changes:e})})}render(){return this.template(this.model)}componentDidMount(){l.findDOMNode(this)._model=this.model}componentWillUnmount(){this.onDestroy();delete l.findDOMNode(this)._model,c.destroyListeners(this);for(const e of this.controllersInstances)e.destroy();this.controllersInstances=[]}onDestroy(){}controllers(){return[]}}t.View=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.DOMEvents=void 0;const r=n(8),o=n(1);t.DOMEvents=class{constructor(){this.listeners=[]}addController(e,t){const n=o.getListeners(e);for(const e of n)this.addListener(e,t)}destroyListeners(e){const t=this.listeners.filter(t=>t.view===e);for(const e of t){e.destroy();const t=this.listeners.indexOf(e);this.listeners.splice(t,1)}}addListener(e,t){if(!o.isDomListener(e))return;const n=new r.DOMListener({eventType:e.eventType,selector:e.selector,handlerArgs:e.handlerArgs,handler:e.handler,view:t});n.listen(),this.listeners.push(n)}}},function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),s=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0}),t.DOMListener=void 0;const i=s(n(0)),l=n(9),c=n(10),u=n(11);t.DOMListener=class{constructor(e){this.eventType=e.eventType,this.selector=e.selector,this.handlerArgs=e.handlerArgs,this.handler=e.handler,this.view=e.view}listen(){this.domHandler=e=>{this.onDOMEvent(e)},document.addEventListener(this.eventType,this.domHandler)}destroy(){document.removeEventListener(this.eventType,this.domHandler),delete this.view,delete this.handler,delete this.domHandler,delete this.handlerArgs}onDOMEvent(e){if(this.isValidEvent(e)){const t=this.getHandlerArgs(e);this.handler(...t)}}isValidEvent(e){const t=i.findDOMNode(this.view);return l.isValidTarget({componentEl:t,selector:this.selector,target:e.target})}getHandlerArgs(e){return this.handlerArgs.map(t=>{if("function"==typeof t){const n=t,r=u.getNearestModelByEvent(e,n);if(!r)throw new Error("cannot find model: "+n.name);return r}return c.getPropertyFromEvent(e,t)})}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isValidTarget=void 0,t.isValidTarget=function(e){let t=e.target,n=!1,r=!1;for(;t;){if("."+t.className===e.selector&&(r=!0),t===e.componentEl){n=!0;break}t=t.parentElement}return n&&r}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getPropertyFromEvent=void 0,t.getPropertyFromEvent=function(e,t){let n=e;for(const e of t)n=n[e];return n}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getNearestModelByEvent=void 0,t.getNearestModelByEvent=function(e,t){let n=e.target;for(;n;){const e=n._model;if(e instanceof t)return e;n=n.parentElement}return null}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Controller=void 0;const r=n(1);t.Controller=class{constructor(e){this.modelListeners=[],this.model=e,this.initModelEvents()}initModelEvents(){const e=r.getListeners(this).filter(e=>r.isModelListener(e));for(const t of e){const e=t.eventType,n=(...e)=>{t.handler(...e)};this.modelListeners.push({eventType:e,handler:n}),this.model.on(e,n)}}destroy(){this.onDestroy();for(const e of this.modelListeners)this.model.removeListener(e.eventType,e.handler);delete this.model}onDestroy(){}}}])})); | ||
//# sourceMappingURL=only-mvc.min.js.map |
@@ -6,2 +6,3 @@ import { Model } from "./Model"; | ||
protected model: Readonly<TModel>; | ||
private modelListeners: any[] = []; | ||
@@ -21,8 +22,31 @@ constructor(model: TModel) { | ||
const eventType = listener.eventType as any; | ||
const handler = (...args: any[]) => { | ||
listener.handler(...args); | ||
}; | ||
this.model.on(eventType, (...args) => { | ||
listener.handler(...args); | ||
this.modelListeners.push({ | ||
eventType, | ||
handler | ||
}); | ||
this.model.on(eventType, handler); | ||
} | ||
} | ||
destroy() { | ||
this.onDestroy(); | ||
for (const modelListener of this.modelListeners) { | ||
this.model.removeListener( | ||
modelListener.eventType, | ||
modelListener.handler | ||
); | ||
} | ||
delete this.model; | ||
} | ||
onDestroy() { | ||
// redefine me | ||
} | ||
} |
@@ -7,2 +7,3 @@ import { Controller } from "./Controller"; | ||
export class DOMEvents { | ||
private listeners: DOMListener[] = []; | ||
@@ -17,2 +18,15 @@ addController(controller: Controller<any>, view: View<any>) { | ||
destroyListeners(view: View<any>) { | ||
const viewListeners = this.listeners.filter(listener => | ||
listener.view === view | ||
); | ||
for (const listener of viewListeners) { | ||
listener.destroy(); | ||
const listenerIndex = this.listeners.indexOf(listener); | ||
this.listeners.splice(listenerIndex, 1); | ||
} | ||
} | ||
private addListener( | ||
@@ -35,4 +49,6 @@ listener: IListener, | ||
domListener.listen(); | ||
this.listeners.push(domListener); | ||
} | ||
} | ||
@@ -17,2 +17,3 @@ import * as ReactDOM from "react-dom"; | ||
export class DOMListener { | ||
view: View<any>; | ||
private eventType: keyof HTMLElementEventMap; | ||
@@ -22,3 +23,3 @@ private selector: string; | ||
private handler: (...args: any[]) => void; | ||
private view: View<any>; | ||
private domHandler!: (...args: any[]) => void; | ||
@@ -31,10 +32,20 @@ constructor(params: IDOMListenerParams) { | ||
this.view = params.view; | ||
} | ||
listen() { | ||
document.addEventListener(this.eventType, (event: Event) => { | ||
this.domHandler = (event: Event) => { | ||
this.onDOMEvent(event); | ||
}); | ||
}; | ||
document.addEventListener(this.eventType, this.domHandler); | ||
} | ||
destroy() { | ||
document.removeEventListener(this.eventType, this.domHandler); | ||
delete this.view; | ||
delete this.handler; | ||
delete this.domHandler; | ||
delete this.handlerArgs; | ||
} | ||
private onDOMEvent(event: Event) { | ||
@@ -41,0 +52,0 @@ if ( this.isValidEvent(event) ) { |
@@ -55,2 +55,23 @@ import * as React from "react"; | ||
componentWillUnmount() { | ||
// clear memory leaks | ||
this.onDestroy(); | ||
const rootEl = ReactDOM.findDOMNode(this) as any; | ||
delete rootEl._model; | ||
domEvents.destroyListeners(this); | ||
for (const controller of this.controllersInstances) { | ||
controller.destroy(); | ||
} | ||
this.controllersInstances = []; | ||
} | ||
onDestroy() { | ||
// redefine me | ||
} | ||
controllers(): (new (model: TModel) => Controller<TModel>)[] { | ||
@@ -57,0 +78,0 @@ return []; |
{ | ||
"name": "mvc-tsx", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "MVC based on React", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5305961
53573