omio - fix render to string

This commit is contained in:
dntzhang 2019-03-19 17:10:08 +08:00
parent 1059aff696
commit 94d649eb75
2 changed files with 123 additions and 70 deletions

View File

@ -58,16 +58,16 @@ export function renderToString(vnode, opts, store, isSvgMode){
opts = Object.assign({
scopedCSS: true
},opts)
const arr = []
const html = _renderToString(vnode, opts, store, isSvgMode, arr)
const css = {}
const html = _renderToString(vnode, opts, store, isSvgMode, css)
return {
css: arr,
css: Object.values(css),
html: html
}
}
/** The default export is an alias of `render()`. */
function _renderToString(vnode, opts, store, isSvgMode, arr) {
function _renderToString(vnode, opts, store, isSvgMode, css) {
if (vnode == null || typeof vnode === 'boolean') {
return '';
}
@ -108,8 +108,7 @@ function _renderToString(vnode, opts, store, isSvgMode, arr) {
const cssStr = c.constructor.css ? c.constructor.css : (typeof c.css === 'function' ? c.css() : c.css)
const cssAttr = '_s' + getCtorName(c.constructor)
arr.push(`<style type="text/css" id="${cssAttr}">${scoper(cssStr, cssAttr)}</style>`)
css[cssAttr] = `<style type="text/css" id="${cssAttr}">${scoper(cssStr, cssAttr)}</style>`
addScopedAttrStatic(
rendered,
'_s' + getCtorName(c.constructor)
@ -120,7 +119,7 @@ function _renderToString(vnode, opts, store, isSvgMode, arr) {
scopeHost(rendered, c.scopedCSSAttr)
}
return _renderToString(rendered, opts, store, false, arr);
return _renderToString(rendered, opts, store, false, css);
}
@ -204,7 +203,7 @@ function _renderToString(vnode, opts, store, isSvgMode, arr) {
let child = vnode.children[i];
if (child != null && child !== false) {
let childSvgMode = nodeName === 'svg' ? true : nodeName === 'foreignObject' ? false : isSvgMode,
ret = _renderToString(child, opts, store, childSvgMode, arr);
ret = _renderToString(child, opts, store, childSvgMode, css);
if (pretty && !hasLarge && isLargeString(ret)) hasLarge = true;
if (ret) pieces.push(ret);
}

View File

@ -41,7 +41,7 @@ describe('render()', () => {
let res = renderToString(<todo-app2 />)
expect(res.html).to.equal('<div _ss0>ab</div>');
expect(res.css+'').to.equal('<style type="text/css" id="_ss0">h3[_ss0]{ color:red; }</style>')
expect(res.css + '').to.equal('<style type="text/css" id="_ss0">h3[_ss0]{ color:red; }</style>')
})
@ -53,75 +53,129 @@ describe('render()', () => {
define('todo-list', class extends WeElement {
css = 'li { color:green; }'
define('todo-list', class extends WeElement {
static css = 'li { color:green; }'
render(props) {
return (
<ul>
{props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
)
}
})
define('todo-app3', class extends WeElement {
static observe = true
css = 'h3 { color:red; }'
data = { items: [], text: '' }
render() {
return (
<div>
<h3>TODO</h3>
<todo-list items={this.data.items} />
<form onSubmit={this.handleSubmit}>
<input
id="new-todo"
onChange={this.handleChange}
value={this.data.text}
/>
<button>Add #{this.data.items.length + 1}</button>
</form>
</div>
)
}
handleChange = e => {
this.data.text = e.target.value
}
handleSubmit = e => {
e.preventDefault()
if (!this.data.text.trim().length) {
return
render(props) {
return (
<ul>
{props.items.map(item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
)
}
this.data.items.push({
text: this.data.text,
id: Date.now()
})
this.data.text = ''
}
})
})
define('todo-app3', class extends WeElement {
static observe = true
static css = 'h3 { color:red; }'
data = { items: [], text: '' }
render() {
return (
<div>
<h3>TODO</h3>
<todo-list items={this.data.items} />
<form onSubmit={this.handleSubmit}>
<input
id="new-todo"
onChange={this.handleChange}
value={this.data.text}
/>
<button>Add #{this.data.items.length + 1}</button>
</form>
</div>
)
}
handleChange = e => {
this.data.text = e.target.value
}
handleSubmit = e => {
e.preventDefault()
if (!this.data.text.trim().length) {
return
}
this.data.items.push({
text: this.data.text,
id: Date.now()
})
this.data.text = ''
}
})
it('render to string with nest element', () => {
let res = renderToString(<todo-app3 />, { scopedCSS: false })
it('render to string with nest element', () => {
let res = renderToString(<todo-app3 />, { scopedCSS: false })
expect(res.html).to.equal('<div><h3>TODO</h3><ul></ul><form><input id="new-todo" value /><button>Add #1</button></form></div>');
})
expect(res.html).to.equal('<div><h3>TODO</h3><ul></ul><form><input id="new-todo" value /><button>Add #1</button></form></div>');
})
it('render to string with nest element and scoped css', () => {
let res = renderToString(<todo-app3 />, { scopedCSS: true })
it('render to string with nest element and scoped css', () => {
let res = renderToString(<todo-app3 />, { scopedCSS: true })
expect(res.html).to.equal('<div _ss1><h3 _ss1>TODO</h3><ul _ss2 _ss1></ul><form _ss1><input id="new-todo" value _ss1 /><button _ss1>Add #1</button></form></div>');
expect(res.css.join('')).to.equal('<style type="text/css" id="_ss1">h3[_ss1]{ color:red; }</style><style type="text/css" id="_ss2">li[_ss2]{ color:green; }</style>')
})
define('todo-app4', class extends WeElement {
static observe = true
static css = 'h3 { color:red; }'
data = { items: [], text: '' }
render() {
return (
<div>
<h3>TODO</h3>
<todo-list items={this.data.items} />
<todo-list items={this.data.items} />
<todo-list items={this.data.items} />
<form onSubmit={this.handleSubmit}>
<input
id="new-todo"
onChange={this.handleChange}
value={this.data.text}
/>
<button>Add #{this.data.items.length + 1}</button>
</form>
</div>
)
}
handleChange = e => {
this.data.text = e.target.value
}
handleSubmit = e => {
e.preventDefault()
if (!this.data.text.trim().length) {
return
}
this.data.items.push({
text: this.data.text,
id: Date.now()
})
this.data.text = ''
}
})
it('render to string with nest element and children elements', () => {
let res = renderToString(<todo-app4 />, { scopedCSS: true })
expect(res.html).to.equal('<div _ss3><h3 _ss3>TODO</h3><ul _ss2 _ss3></ul><ul _ss2 _ss3></ul><ul _ss2 _ss3></ul><form _ss3><input id="new-todo" value _ss3 /><button _ss3>Add #1</button></form></div>');
expect(res.css.join('')).to.equal('<style type="text/css" id="_ss3">h3[_ss3]{ color:red; }</style><style type="text/css" id="_ss2">li[_ss2]{ color:green; }</style>')
})
expect(res.html).to.equal('<div _ss1><h3 _ss1>TODO</h3><ul _ss2 _ss1></ul><form _ss1><input id="new-todo" value _ss1 /><button _ss1>Add #1</button></form></div>');
expect(res.css.join('')).to.equal('<style type="text/css" id="_ss1">h3[_ss1]{ color:red; }</style><style type="text/css" id="_ss2">li[_ss2]{ color:green; }</style>')
})
})