2017-08-12 15 views
5

वहाँ एक इनपुट के रूप स्वच्छ अभी तक यादृच्छिक एचटीएमएल तार के साथ गैर एसपीए परिदृश्य है:एचटीएमएल स्ट्रिंग प्रस्तुत isomorphic प्रतिक्रिया अनुप्रयोग में

<p>...</p> 
<p>...</p> 
<gallery image-ids=""/> 
<player video-id="..."/> 
<p>...</p> 

स्ट्रिंग WYSIWYG संपादक से निकलती है और एकत्रित नियमित HTML टैग और की एक सीमित संख्या में शामिल है कस्टम तत्व (घटक) जिन्हें विजेट्स में प्रस्तुत किया जाना चाहिए।

वर्तमान में इस तरह के HTML स्निपेट को सर्वर साइड (एक्सप्रेस) पर अलग से प्रस्तुत किया जाना चाहिए, लेकिन अंततः आइसोमोर्फिक एप्लिकेशन के हिस्से के रूप में क्लाइंट साइड पर भी प्रस्तुत किया जाएगा।

मैं घटकों को लागू करने के लिए प्रतिक्रिया (या प्रतिक्रिया-जैसे ढांचे) का उपयोग करना चाहता हूं क्योंकि यह संभवतः मामले के अनुरूप है - यह आइसोमोर्फिक है और आंशिक रूप से प्रस्तुत करता है।

समस्या यह है कि

<gallery image-ids="[1, 3]"/> 

तरह सबस्ट्रिंग हो जाना चाहिए है

<Gallery imageIds={[1, 3]}/> 
कुछ बिंदु पर

JSX/TSX घटक है, और मुझे यकीन है कि क्या यह करने के लिए सही तरीका है नहीं कर रहा हूँ, लेकिन मैं उम्मीद करता हूं कि यह एक आम काम होगा।

इस मामले को प्रतिक्रिया में कैसे हल किया जा सकता है?

+0

ऐसा लगता है कि आप एक प्रतिक्रिया घटक में '' जैसे तारों को चालू करने के लिए कह रहे हैं - बहुत उचित नहीं लगता है। क्या मैं जान सकता हूं क्यों? यदि आवश्यकता हो तो क्या आप अपने प्रश्न को फिर से लिख सकते हैं? –

+0

प्रश्न में पहले से ही समस्या के संदर्भ में जानकारी शामिल है। स्ट्रिंग WYSIWYG संपादक से उत्पन्न होती है। – estus

+0

और आप इसे एक प्रतिक्रिया घटक में बदलना चाहते हैं? परंपरागत रूप से यह चारों ओर एक और तरीका रहा है - घटक => (प्रतिक्रिया + प्रतिक्रिया-डोम) => htmlString। आपके द्वारा उल्लिखित मामले को छोड़कर, आप अभी यह कैसे कर रहे हैं? जो मैं समझने में असफल रहा हूं क्या आप WYSIWYG से उत्पन्न एचटीएमएल को घटक को प्रतिक्रिया देने के लिए स्वचालित तरीके की तलाश कर रहे हैं? या क्या कस्टम तत्वों की एक सूची है जिसे आप रिट/प्रतिक्रिया-जैसे lib के लिए पोर्ट करना चाहते हैं। –

उत्तर

5

साफ़ किया एचटीएमएल अवयव कि सर्वर और ग्राहक पर दोनों एचटीएमएल स्ट्रिंग को पार्स और तत्वों प्रतिक्रिया में जिसके परिणामस्वरूप नोड्स बदलने से चलाया जा सकता है प्रतिक्रिया में बदल सकता है।

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 कि तुम सच में, जरूरत के रूप में आप का उल्लेख नहीं है, लेकिन के लिए एक पेड़ (इस मामले में ReactDOM) प्रतिक्रिया रेंडरर के लिए नोड्स प्रतिक्रिया। जेएसएक्स सिर्फ सिंटैक्टिक चीनी है, और इसे आगे और पीछे बदलना अनावश्यक है जब तक कि आप अपने कोडबेस में प्रतिक्रिया आउटपुट को बनाए रखना नहीं चाहते हैं।

अधिक सरलीकृत एचटीएमएल पार्सिंग क्षमा करें। यह केवल चित्रकारी उद्देश्यों के लिए है। इनपुट इनपुट एचटीएमएल या आपके उपयोग के मामले में फिट बैठने के लिए आप एक और स्पेक-अनुपालन लाइब्रेरी का उपयोग करना चाह सकते हैं।

सुनिश्चित करें कि क्लाइंट साइड बंडल ठीक उसी App घटक प्राप्त करें, अन्यथा आप प्रतिक्रिया कर सकते हैं क्लाइंट साइड स्क्रिप्ट डीओएम पेड़ को फिर से बनायेगी और आप सर्वर साइड प्रतिपादन के सभी लाभ खो देंगे।

आप ऊपर दिए गए दृष्टिकोण के साथ प्रतिक्रिया 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 
) 
); 

कस्टम के साथ सावधानी से जिम्मेदार बताते हैं - आप this rfc पालन करने के लिए चाहते हो सकता है। यदि संभव हो तो ऊंट के साथ चिपकाएं।

+0

मुझे यह जवाब अपने आप से बेहतर है।:) – Jeff

+0

धन्यवाद :) प्रोप –

+0

के साथ मेरा उत्तर अपडेट करना धन्यवाद, यही वह चीज है जिसे मैं ढूंढ रहा था। यह बहुत अच्छा है कि अनुमत घटकों के सेट पर प्रतिबंध के परिणामस्वरूप आसान ट्रैवर्सिंग होती है। – estus

2

आप स्ट्रिंग को निष्पादन योग्य जावास्क्रिप्ट में बदलने के लिए बैबेल एपीआई का उपयोग कर सकते हैं।

आप अपने जीवन रास्ता आसान अगर आप <lovercase> कस्टम घटक सम्मेलन खाई, कर सकते हैं, क्योंकि JSX में वे डोम टैग की तरह व्यवहार कर रहे हैं, इसलिए यदि आप अपने उपयोगकर्ताओं <gallery> के बजाय <Gallery> का उपयोग कर सकते हैं यदि आप एक से अपने आप को बचा लेगा बहुत परेशानी

मैंने आपके लिए एक कामकाजी (लेकिन बदसूरत) CodeSandbox बनाया है। विचार जेएसएक्स को कोड में संकलित करने के लिए बेबेल का उपयोग करना है, फिर उस कोड का मूल्यांकन करें। हालांकि सावधान रहें, यदि उपयोगकर्ता इसे संपादित कर सकते हैं, तो वे निश्चित रूप से दुर्भावनापूर्ण कोड इंजेक्ट कर सकते हैं!

जे एस कोड:

import React from 'react' 
import * as Babel from 'babel-standalone' 
import { render } from 'react-dom' 

console.clear() 

const state = { 
    code: ` 
    Hey! 
    <Gallery hello="world" /> 
    Awesome! 
` 
} 


const changeCode = (e) => { 
    state.code = e.target.value 
    compileCode() 
    renderApp() 
} 

const compileCode =() => { 
    const template = ` 
function _render (React, Gallery) { 
    return (
    <div> 
    ${state.code} 
    </div> 
) 
} 
` 
    state.error = '' 
    try { 
    const t = Babel.transform(template, { 
     presets: ['react'] 
    }) 

    state.compiled = new Function(`return (${t.code}).apply(null, arguments);`)(React, Gallery) 
    } catch (err) { 
    state.error = err.message 
    } 
} 

const Gallery = ({ hello }) => 
    <div>Here be a gallery: {hello}</div> 

const App =() => (
    <div> 
    <textarea style={{ width: '100%', display: 'block' }} onChange={changeCode} rows={10} value={state.code}></textarea> 
    <div style={{ backgroundColor: '#e0e9ef', padding: 10 }}> 
    {state.error ? state.error : state.compiled} 
    </div> 
    </div> 
) 


const renderApp =() => 
    render(<App />, document.getElementById('root')); 

compileCode() 
renderApp() 
+0

हां, इसे eval का उपयोग करने की आवश्यकता है, इसलिए यह उपयोगकर्ता इनपुट के लिए अपने वर्तमान रूप में व्यावहारिक नहीं है। क्या आप समझ सकते हैं कि 'रास्ता आसान' से आपका क्या मतलब है? '' एक * स्ट्रिंग * किसी भी तरह से होगा, है ना? – estus

+0

आपको फ़ंक्शन कॉल या कुछ को कम करने के तरीके के रूप में एएसटी की जांच करनी होगी, वास्तव में कोई अन्य तरीका नहीं है। ' 'के बारे में, नहीं, जेएसएक्स को' React.createElement (गैलरी, ...) 'में बदल दिया गया है जबकि' 'को' React.createElement ('गैलरी', ...) में बदल दिया गया है। – Jeff

+0

मैं नहीं देखता कि मैं अपना जीवन तरीका कैसे आसान बना सकता हूं। संकलित HTML एक स्ट्रिंग है जिसे क्लाइंट साइड से पुनर्प्राप्त किया गया था और डीबी में संग्रहीत किया गया था। यह एक स्ट्रिंग के अलावा कुछ भी नहीं हो सकता है। इसलिए सवाल है। – estus

संबंधित मुद्दे