Ramda — 使用函数组合构建字符串
Ramda — Building string with function composition
我有一个像这样的已解析 DOM 对象
const element = {
name: 'div',
content: 'foo'
}
我想以 FP 方式将其转换回字符串
const openTag = element => `<${element.name}>`;
const closeTag = element => `</${element.name}>`;
const setContent = element => element.content;
// desired way but obviously won't work
pipe(
openTag,
setContent,
closeTag
)(element)
// desired output <div>foo</div>
如何使用 Ramda 实现类似的结构?
这行得通
const toHTML = pipe(
juxt([openTag, setContent, closeTag]),
join('')
);
用法:
toHTML(element) // -> "<div>foo</div>"
答案的原始版本使用 ap()
而不是 juxt()
,但这会导致一些用法上的丑陋,因为 ap
被定义为
ap
applies a list of functions to a list of values.
并且使用需要一个额外的数组
toHTML([element]) // -> "<div>foo</div>"
向 Scott Sauyet 致敬,因为他在评论中指出了这一点。
简单而实用:
const html = (tag, content) => `<${tag}>${content}</${tag}>`;
并且可以组成:
const toHTML = compose(apply(html), props(['name', 'content']));
toHTML({name: 'div', content: 'foo'});
//=> "<div>foo</div>"
我个人会使用数组来表示标记:
<div title="Foobarbaz!">
<span>foo</span>
<span style="font-weight:bold">bar</span>
baz
</div>
可以表示为:
['div', {title: 'Foobarbaz!'},
['span', null, 'foo'],
['span', {style: 'font-weight:bold'}, 'bar'],
'baz']
然后您可以递归地处理该结构:
const html =
([tag, attr, ...children]) => `
<${tag} ${Object.entries(attr || {}).map(([k, v]) => `${k}="${v}"`).join(' ')}>
${children.map(
child => Array.isArray(child)
? html(child)
: child
).join('')}
</${tag}>
`;
console.log(
html(['div', {title: 'Foobarbaz!'},
['span', null, 'foo'],
['span', {style: 'font-weight:bold'}, 'bar'],
'baz'])
);
生成 HTML 时你应该担心 XSS 而不是 FP ;)
我有一个像这样的已解析 DOM 对象
const element = {
name: 'div',
content: 'foo'
}
我想以 FP 方式将其转换回字符串
const openTag = element => `<${element.name}>`;
const closeTag = element => `</${element.name}>`;
const setContent = element => element.content;
// desired way but obviously won't work
pipe(
openTag,
setContent,
closeTag
)(element)
// desired output <div>foo</div>
如何使用 Ramda 实现类似的结构?
这行得通
const toHTML = pipe(
juxt([openTag, setContent, closeTag]),
join('')
);
用法:
toHTML(element) // -> "<div>foo</div>"
答案的原始版本使用 ap()
而不是 juxt()
,但这会导致一些用法上的丑陋,因为 ap
被定义为
ap
applies a list of functions to a list of values.
并且使用需要一个额外的数组
toHTML([element]) // -> "<div>foo</div>"
向 Scott Sauyet 致敬,因为他在评论中指出了这一点。
简单而实用:
const html = (tag, content) => `<${tag}>${content}</${tag}>`;
并且可以组成:
const toHTML = compose(apply(html), props(['name', 'content']));
toHTML({name: 'div', content: 'foo'});
//=> "<div>foo</div>"
我个人会使用数组来表示标记:
<div title="Foobarbaz!">
<span>foo</span>
<span style="font-weight:bold">bar</span>
baz
</div>
可以表示为:
['div', {title: 'Foobarbaz!'},
['span', null, 'foo'],
['span', {style: 'font-weight:bold'}, 'bar'],
'baz']
然后您可以递归地处理该结构:
const html =
([tag, attr, ...children]) => `
<${tag} ${Object.entries(attr || {}).map(([k, v]) => `${k}="${v}"`).join(' ')}>
${children.map(
child => Array.isArray(child)
? html(child)
: child
).join('')}
</${tag}>
`;
console.log(
html(['div', {title: 'Foobarbaz!'},
['span', null, 'foo'],
['span', {style: 'font-weight:bold'}, 'bar'],
'baz'])
);
生成 HTML 时你应该担心 XSS 而不是 FP ;)