CJQ
Componentized JQuery
by jeyssonguevara
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
<div id="app">
</div>
JavaScript
// Componentized JQuery
(function($, exports) {
function StatefulComponent(props, render) {
const {
key
} = props;
key === undefined && console.warn(`At [${render.name}]: Stateful components should have a 'key' prop in order to recover state if the parent component gets re-rendered.`);
let state = [];
let statesCount = 0;
let changedIndexes = [];
const effects = [];
const reducibleState = {
isNew: true,
data: undefined,
init: (initial) => {
if (this.isNew) {
this.data = initial;
}
}
};
let needsReRender = false;
let $currentElement = undefined;
const scheduleRender = () => {
if (!needsReRender) {
needsReRender = true;
setTimeout(() => this.doRender(), 0);
}
};
const tryRecoverState = () => {
if (!key) {
return;
}
const $recoveredElement = $(`[data-key="${key}"]`);
if ($recoveredElement.length > 0) {
$currentElement = $recoveredElement;
state = JSON.parse($currentElement.attr('data-state'));
reducibleState.init(JSON.parse($currentElement.attr('data-reducible-state')));
}
};
const saveState = () => {
if (key) {
$currentElement.attr('data-key', key);
}
return $currentElement.attr({
'data-state': JSON.stringify(state),
'data-reducible-state': JSON.stringify(reducibleState.data || {}),
});
}
tryRecoverState();
const use = {
state: (initial) => {
const currentIndex = statesCount;
if (!$currentElement) {
state.push(initial);
}
statesCount++;
return [
state[currentIndex],
(newValue, {
shouldRender = true
} = {}) => {
state[currentIndex] = newValue;
changedIndexes.push(currentIndex);
if...