Skip to content

Instantly share code, notes, and snippets.

@rohozhnikoff
Last active November 6, 2015 19:15
Show Gist options
  • Save rohozhnikoff/1e203a067901039e99e2 to your computer and use it in GitHub Desktop.
Save rohozhnikoff/1e203a067901039e99e2 to your computer and use it in GitHub Desktop.
jquery-to-react quick concept
/* генерим react-компоненты из под серверных шаблонов */
var ReactDOM = require('react-dom');
var React = require('react');
const findAndRender = (function () {
const options = {
className: 'jr',
classNameActivated: 'jr-activated'
};
/**
* @credits: https://github.com/bitovi/jquerypp/blob/master/event/removed/removed.js
* */
(function () {
// Store the old jQuery.cleanData
var oldClean = $.cleanData;
// Overwrites cleanData which is called by jQuery on manipulation methods
$.cleanData = function (elems) {
for (var i = 0, elem;
(elem = elems[i]) !== undefined; i++) {
// Trigger the destroyed event
$(elem).triggerHandler("removed");
}
// Call the old jQuery.cleanData
oldClean(elems);
};
})();
return function ({dom, components}) {
$(`.${options.className}:not(.${options.classNameActivated})`, dom).each(function () {
var domEl = this,
jqEl = $(this),
propsFromData = jqEl.data() || {},
component = components[propsFromData.component];
if (!component) {
return console.error('Didnt find component', data.component, jqEl)
}
const updateInDom = (function () {
var props = {};
return function (component, newProps, children) {
props = Object.assign(props || {}, newProps)
ReactDOM.render(
React.createFactory(component)(
props,
getReactNodesFromTree(getReactCompatibleTreeFromDomNode(children))
),
domEl
);
}
})();
updateInDom(
component,
Object.assign({}, propsFromData, {component: undefined}),
jqEl.children().get()
);
// кешируем, отмечаем выполненными
jqEl.data('update', updateInDom).addClass(options.classNameActivated);
jqEl.on('removed', function () {
ReactDOM.unmountComponentAtNode(this);
});
})
}
})();
module.exports = {
//render: findAndRender,
init: function (componentsHash) {
// todo: $?
// init on jquery dom ready
$(function () {
findAndRender({
dom: document.body,
components: Object.assign({}, componentsHash)
})
});
}
};
function getReactNodesFromTree(tree){
if(!(tree instanceof Array)) tree = [tree];
return tree.map(function(el, i){
if(typeof el === 'string') return el;
return React.createElement(
el.tag,
Object.assign({}, {key: i}, el.props),
el.children.length > 0 ? getReactNodesFromTree(el.children) : undefined
)
})
}
/* превращаем коллекцию дом-нод в дерево для реакта */
function getReactCompatibleTreeFromDomNode(node) {
if (node instanceof NodeList || node instanceof Array) {
return toArray(node).map(getReactCompatibleTreeFromDomNode)
} else if (node.nodeName === '#text') {
return node.nodeValue
}
var props = reduceTree(nodeAttrsToTree(node.attributes), function (memo, value, key) {
if (key === 'class') key = 'className';
memo[key] = value;
return memo;
}, {});
return {
tag: node.nodeName.toLowerCase(),
props: props,
children: node.childNodes ? getReactCompatibleTreeFromDomNode(node.childNodes) : []
}
}
function reduceTree(hash, iterator, memo) {
for (var key in hash) {
memo = iterator(memo, hash[key], key, hash)
}
return memo
}
function toArray(arr) {
return Array.prototype.slice.call(arr, 0)
}
function nodeAttrsToTree(map) {
var hash = {};
if (!map) return hash;
for (var i = 0; i < map.length; i++) {
hash[map[i].nodeName] = map[i].nodeValue
}
return hash
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment