可以通过将html字符串解析并将生成的节点转换为React元素,将经过处理的HTML转换为可在服务器和客户端上运行的React组件。
const React = require('react');const ReactDOMServer = require('react-dom/server');const str = `<div>divContent<p> para 1</p><p> para 2</p><gallery image-ids="" /><player video-id="" /><p> para 3</p><gallery image-ids="[1, 3]"/></div>`;var parse = require('xml-parser');const Gallery = () => React.createElement('div', null, 'Gallery comp');const Player = () => React.createElement('div', null, 'Player comp');const componentMap = { gallery: Gallery, player: Player};const traverse = (cur, props) => { return React.createElement( componentMap[cur.name] || cur.name, props, cur.children.length === 0 ? cur.content: Array.prototype.map.call(cur.children, (c, i) => traverse(c, { key: i })) );};const domTree = parse(str).root;const App = traverse( domTree);console.log( ReactDOMServer.renderToString( App ));
但是请注意,您并不是真正需要的JSX / TSX,而是React渲染器的React
Nodes树(在这种情况下为ReactDOM)。JSX只是语法糖,除非您想在代码库中维护React输出,否则不需要来回转换它。
请原谅过度简化的html解析。它仅用于说明目的。您可能想使用符合规范的库来解析输入的html或适合您的用例的内容。
确保客户端捆绑软件获得完全相同的
App组件,否则您可能会因为React的客户端脚本重新创建DOM树而失去服务器渲染的所有好处。
您也可以通过上述方法利用React 16的流式传输。
解决道具问题
道具将从树中作为属性提供给您,并且可以作为道具传递(在仔细考虑课程用例的情况下)。
const React = require('react');const ReactDOMServer = require('react-dom/server');const str = `<div>divContent<p> para 1</p><p> para 2</p><gallery image-ids="" /><player video-id="" /><p> para 3</p><gallery image-ids="[1, 3]"/></div>`;var parse = require('xml-parser');const Gallery = props => React.createElement('div', null, `Gallery comp: Props ${JSON.stringify(props)}`);const Player = () => React.createElement('div', null, 'Player comp');const componentMap = { gallery: Gallery, player: Player};const attrsToProps = attributes => { return Object.keys(attributes).reduce((acc, k) => { let val; try { val = JSON.parse(attributes[k]) } catch(e) { val = null; } return Object.assign( {}, acc, { [ k.replace(/-/g, '') ]: val } ); }, {});};const traverse = (cur, props) => { const propsFromAttrs = attrsToProps(cur.attributes); const childrenNodes = Array.prototype.map.call(cur.children, (c, i) => { return traverse( c, Object.assign( {}, { key: i } ) ); }); return React.createElement( componentMap[cur.name] || cur.name, Object.assign( {}, props, propsFromAttrs ), cur.children.length === 0 ? cur.content: childrenNodes );};const domTree = parse(str).root;const App = traverse( domTree);console.log( ReactDOMServer.renderToString( App ));
但是请谨慎使用自定义属性-
您可能要遵循此rfc。如果可能,请坚持使用camelCase。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)