JSFiddle - React, Tailwind, and code Playground
by Ilya
JavaScript
class Block {
static EVENTS = {
INIT: "init",
FLOW_CDM: "flow:component-did-mount",
FLOW_CDU: "flow:component-did-update",
FLOW_RENDER: "flow:render"
};
_element = null;
_meta = null;
/** JSDoc
* @param {string} tagName
* @param {Object} props
*
* @returns {void}
*/
constructor(tagName = "div", props = {}) {
const eventBus = new EventBus();
this._meta = {
tagName,
props
};
this.props = this._makePropsProxy(props);
this.eventBus = () => eventBus;
this._registerEvents(eventBus);
eventBus.emit(Block.EVENTS.INIT);
}
_registerEvents(eventBus) {
eventBus.on(Block.EVENTS.INIT, this.init.bind(this));
eventBus.on(Block.EVENTS.FLOW_CDM, this._componentDidMount.bind(this));
eventBus.on(Block.EVENTS.FLOW_CDU, this._componentDidUpdate.bind(this));
eventBus.on(Block.EVENTS.FLOW_RENDER, this._render.bind(this));
}
_createResources() {
const { tagName } = this._meta;
this._element = this._createDocumentElement(tagName);
}
init() {
this._createResources();
this.eventBus().emit(Block.EVENTS.FLOW_RENDER);
}
_componentDidMount() {
this.componentDidMount();
Object.values(this.children).forEach(child => {
child.dispatchComponentDidMount();
});
}
// Может переопределять пользователь, необязательно трогать
componentDidMount(oldProps) {
}
dispatchComponentDidMoun() {
this.eventBus().emit(Block.EVENTS.FLOW_CDM);
}
_componentDidUpdate(oldProps, newProps) {
const response = this.componentDidUpdate(oldProps, newProps);
if (response) {
this.eventBus().emit(Block.EVENTS.FLOW_RENDER);
}
}
// Может переопределять пользователь, необязательно трогать
componentDidUpdate(oldProps, newProps) {
return oldProps !== newProps;
}
setProps = nextProps => {
if (!nextProps) {
return;
}
Object.assign(this.props, nextProps);
};
get element() {
return this._element;
}
_render() {
const block = this.render();
this._removeEvents();
this._element!.innerHTML = block;
...