如何解析古登堡块中的元素数组

时间:2019-03-30 作者:Sam Schneider

我有一个自定义Gutenberg块,它试图获取字符串数组并将其另存为<li> 元素。所有内容都按预期工作,并正确显示给最终用户,但我在重新加载编辑器后遇到验证错误。

以下是验证错误:

Expected:

<div class="wp-block-ggcn-blocks-query-string-content"><span class="data-drop" newtab=""></span><ul class="tabs"><li class="tab"><li class="tab">Tab1</li></li><li class="tab"><li class="tab">Tab2</li></li></ul><p class="custom-content"></p></div>

Actual:

<div class="wp-block-ggcn-blocks-query-string-content"><span class="data-drop" newtab=""></span><ul class="tabs"><li class="tab">Tab1</li><li class="tab">Tab2</li></ul><p class="custom-content"></p></div>
以下是我的保存功能:

save({attributes, className}) {
  const { tabs, newTab, content } = attributes;

  return (
    <div className={className}>
      <span className="data-drop" newtab={newTab}></span>
      <ul className="tabs">
      {tabs.map(tab => {
            return <li className="tab">{tab}</li>;
        })}
      </ul>          
    </div>
  );
}
下面是我如何解析属性的:

attributes: {
  tabs: { 
    type: \'array\',
    source: \'children\',
    selector: \'ul.tabs\',
    default: []
  }
}
显然,我正在解析整个HTML列表元素,而我只需要文本。但当我将选择器更改为ul.tabs > li, 我只得到单个元素的文本,超过1个项目的列表未通过验证。

有人能帮我理解如何获取文本值数组吗?

2 个回复
SO网友:Sam Schneider

我找到了一个变通方法,由@tmdesigned的答案引发,我将把它作为一个答案发布。这并不漂亮,我不认为这是一个“经典”的答案,但希望它能帮助我们实现这一目标。

首先,我使用source: children:

tabs: { 
  type: \'array\',
  source: \'children\',
  selector: \'ul.tabs\',
  default: []
}
这意味着在初始保存时,我处理的是一个字符串数组,但在编辑器中的后续加载时,我处理的是一个对象数组,因为我源类型的子对象是<li> 元素本身,而不是元素的文本值。

我的解决方案是映射这些元素并将它们转换回字符串数组。这必须在edit 功能和save 作用

const tabValues = tabs.map(tab => {
  if (typeof(tab) === \'object\')
    return tab.props.children[0];

  return tab;
});
后来在输出中,我可以这样输出:

{tabValues.map(tab => <li key={tab} className="tab">{tab}</li>)}
如果任何人有一个完全依赖于数据解析的解决方案,并且不需要这种变通方法,我会将其标记为答案。

SO网友:tmdesigned

当您将属性的源设置为子级时,它将为您提供DOM元素,即包括包装HTML而不仅仅是内部文本。

因此,您看到的行为(您可能已经知道)是HTML元素嵌套在其内部。你在把里面的东西包起来<li>, 它被包裹在<li>, 可能会被<li> 再次,等等。

那部分我很确定。下面的解决方案是我对如何操作的理解,但还没有完成这种类型的属性选择器,我还没有完全测试它。话虽如此,我认为您所寻找的更接近:

attributes: {
  tabs: { 
    type: \'array\',
    source: \'query\',
    selector: \'ul.tabs\',
    default: [],
    query: {
      val: {
        type: \'string\',
        selector: \'li\',
        source: \'text\',
    },
  }
}
因此,我们正在创建一个具有一个属性的对象数组,该属性来自每个子对象的文本。然后在save函数中,您必须特别地val 我们刚刚指定的属性来自li 选择器:

save({attributes, className}) {
  const { tabs, newTab, content } = attributes;

  return (
    <div className={className}>
      <span className="data-drop" newtab={newTab}></span>
      <ul className="tabs">
      {tabs.map(tab => {
            return <li className="tab">{tab.val}</li>;
        })}
      </ul>          
    </div>
  );
}

相关推荐