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 ;)