Last active
November 6, 2015 19:15
-
-
Save rohozhnikoff/1e203a067901039e99e2 to your computer and use it in GitHub Desktop.
jquery-to-react quick concept
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* генерим 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