我正在尝试扩展core/table
阻止和复制粘贴、跟踪和出错,使我接近我要做的事情。但我觉得这不是我喜欢的。
我喜欢扩展块,使其具有控制<table>
该块已经对两个基类执行了此操作,但我希望它能够与Bootstrap CSS tables.
原始块代码can be found here.
我喜欢做的是古腾堡也做得很好的事情,而对于桌块来说,就是为了风格。当您将其设置为“条带化”时,它将添加is-style-striped
到街区。它将实时更新该字段,一旦手动删除该类,它将自动将样式切换为“默认”。我喜欢将一些类切换链接到这样的文本字段。我在GB代码中搜索了一点,但找不到它的位置和方式。这个buildTableClasses
使用的函数classnames/dedupe
可能是一种方式,但这里有一些问题。
<ToggleControl
label={ __( \'Hover\' ) }
checked={ !! tableHover }
onChange={ () => props.setAttributes( {
tableHover: ! tableHover,
tableClass: buildTableClasses( props.attributes ),
} ) }
/>
我不太明白这里使用的否定和双重否定。这段代码基于我找到的一些教程。目前,is行为怪异。就像反向切换一样,当切换关闭时会添加类,但当切换最后一个类所坚持的另一个切换时也会添加类,有些奇怪。我试过了,但它完全坏了,所以我就这样贴了出来块原来已经具有的表的后台类不会在“table classes”文本控件字段中结束手动从字段中删除类时,更改不会绑定到切换。所以我想找到一种方法来实现这一点。我可以为它写一个函数,但我想知道是否有更好的方法来完成这一切。可能最好重用一些GB核心代码或在其之后对代码进行建模。如果你能指出正确的方向那就太好了我想知道如何扩展已经存在的部分,比如添加新控件。或者删除一个类似于生成的样式部分的部分。因为Bootstrap有太多的类,所以可以组合控制样式,样式的组合将是巨大的,所以类切换可能是更好的方法在玩这个游戏的过程中,我注意到它有时会破坏块,而GB似乎会对输出进行一些检查,实际上无法恢复块。因此,我想知道我是否应该分岔,但维护起来会很烦人。但是如果一个扩展块在过滤器进入或移除时打断了用户的块,那么这个解决方案就不太好了我目前拥有的完整代码。
Ready to try plugin on Github. 这个
save
函数是从GB复制粘贴的,并针对表类进行了修改。
import classnames from \'classnames/dedupe\';
const wp = window.wp;
const { __ } = wp.i18n;
const { addFilter } = wp.hooks;
const { assign } = window.lodash;
const {
createHigherOrderComponent,
} = wp.compose;
const {
Fragment,
} = wp.element;
const {
RichText,
InspectorControls,
getColorClassName,
} = wp.editor;
const {
PanelBody,
TextControl,
ToggleControl,
} = wp.components;
const filterBlocks = ( settings ) => {
console.log( settings );
if ( settings.name !== \'core/table\' ) {
return settings;
}
const newSettings = {
...settings,
attributes: {
...settings.attributes, // spread in old attributes so we don\'t lose them!
tableClass: { // here is our new attribute
type: \'string\',
default: \'table \',
},
tableBordered: { // here is our new attribute
type: \'boolean\',
default: false,
},
tableStriped: { // here is our new attribute
type: \'boolean\',
default: false,
},
tableHover: { // here is our new attribute
type: \'boolean\',
default: true,
},
},
save( { attributes } ) {
const {
hasFixedLayout,
head,
body,
foot,
backgroundColor,
caption,
tableBordered,
tableStriped,
tableHover,
tableClass,
} = attributes;
const isEmpty = ! head.length && ! body.length && ! foot.length;
if ( isEmpty ) {
return null;
}
const classes = buildTableClasses( attributes );
const hasCaption = ! RichText.isEmpty( caption );
const Section = ( { type, rows } ) => {
if ( ! rows.length ) {
return null;
}
const Tag = `t${ type }`;
return (
<Tag>
{ rows.map( ( { cells }, rowIndex ) => (
<tr key={ rowIndex }>
{ cells.map(
( { content, tag, scope, align }, cellIndex ) => {
const cellClasses = classnames( {
[ `has-text-align-${ align }` ]: align,
} );
return (
<RichText.Content
className={
cellClasses ?
cellClasses :
undefined
}
data-align={ align }
tagName={ tag }
value={ content }
key={ cellIndex }
scope={
tag === \'th\' ? scope : undefined
}
/>
);
}
) }
</tr>
) ) }
</Tag>
);
};
return (
<figure>
<table className={ classes === \'\' ? undefined : classes }>
<Section type="head" rows={ head } />
<Section type="body" rows={ body } />
<Section type="foot" rows={ foot } />
</table>
{ hasCaption && (
<RichText.Content tagName="figcaption" value={ caption } />
) }
</figure>
);
},
};
return newSettings;
};
addFilter(
\'blocks.registerBlockType\',
\'example/filter-blocks\',
filterBlocks
);
function buildTableClasses( attributes ) {
const {
hasFixedLayout,
backgroundClass,
tableStriped,
tableBordered,
tableHover,
tableClass,
} = attributes;
const classes = classnames(
tableClass.split( \' \' ),
backgroundClass,
{
table: true,
\'has-fixed-layout\': hasFixedLayout,
\'has-background\': !! backgroundClass,
\'table-bordered\': tableBordered,
\'table-striped\': tableStriped,
\'table-hover\': tableHover,
}
);
return classes;
}
const tableClassControl = createHigherOrderComponent( ( BlockEdit ) => {
return ( props ) => {
if ( \'core/table\' !== props.name ) {
return (
<BlockEdit { ...props } />
);
}
const {
tableStriped,
tableBordered,
tableHover,
tableClass,
} = props.attributes;
return (
<Fragment>
<BlockEdit { ...props } />
<InspectorControls>
<PanelBody
title={ __( \'Table classes\' ) }
initialOpen={ true }
>
<ToggleControl
label={ __( \'Striped\' ) }
checked={ !! tableStriped }
onChange={ () => props.setAttributes( {
tableStriped: ! tableStriped,
tableClass: buildTableClasses( props.attributes ),
} ) }
/>
<ToggleControl
label={ __( \'Bordered\' ) }
checked={ !! tableBordered }
onChange={ () => props.setAttributes( {
tableBordered: ! tableBordered,
tableClass: buildTableClasses( props.attributes ),
} ) }
/>
<ToggleControl
label={ __( \'Hover\' ) }
checked={ !! tableHover }
onChange={ () => props.setAttributes( {
tableHover: ! tableHover,
tableClass: buildTableClasses( props.attributes ),
} ) }
/>
<TextControl
label={ __( \'<table> classes\' ) }
type="text"
value={ tableClass }
onChange={ ( value ) =>
props.setAttributes( { tableClass: value } )
}
/>
</PanelBody>
</InspectorControls>
</Fragment>
);
};
}, \'tableClassControl\' );
addFilter( \'editor.BlockEdit\', \'extend-block-example/with-spacing-control\', tableClassControl );
最合适的回答,由SO网友:Sally CJ 整理而成
双NOT运算符(!!
)
这只是一种将非布尔值转换/类型转换为布尔值的方法,并且
!! <expression>
给了我们相反的
! <expression>
.
let foo = \'bar\'; // non-empty string
console.log( ! foo, !! foo ); // false, true
foo = \'\'; // now it\'s an empty string
console.log( ! foo, !! foo ); // true, false
<代码中的问题
wp.editor
works,它已被弃用,因此您应该使用
wp.blockEditor
而是:
const {
RichText,
InspectorControls,
getColorClassName
} = wp.blockEditor; // not wp.editor
英寸buildTableClasses()
, backgroundClass
不是块中的属性。所以(第一个)应该是backgroundColor
并定义backgroundClass
像这样:const backgroundClass = getColorClassName(
\'background-color\',
backgroundColor
);
buildTableClasses()
只能与一起使用save
函数,因为从edit
函数,您将得到;倒置的“;问题,因为函数将接收旧属性。我将使用专用功能更新;<table>
“类别”;字段更新切换控件时,仅添加/删除与该切换关联的类,例如。table-hover
对于;悬停(&Q);切换:
function onChangeTableHover() {
props.setAttributes( {
// Toggle the state.
tableHover: ! tableHover,
// Then add/remove only the table-hover class.
tableClass: classnames( tableClass, {
\'table-hover\': ! tableHover,
} ),
} );
}
/* Then in the JSX:
<ToggleControl
label={ __( \'Hover\' ) }
checked={ !! tableHover }
onChange={ onChangeTableHover }
/>
*/
您可能正在考虑背景颜色类,但它们应该由颜色选择器开关控制(添加/删除)(在“颜色设置”面板/部分中)。当;<table>
“类别”;字段已更新,例如您键入table-hover
在此处或将其删除时,应更改切换状态:
function onChangeTableClass( value ) {
// User likely typed a whitespace.
if ( tableClass === value.trim() ) {
props.setAttributes( { tableClass: value } );
return;
}
const list = value.split( / +/ );
props.setAttributes( {
// Update the value.
tableClass: classnames( value ),
// Then the toggles.
tableHover: list.indexOf( \'table-hover\' ) >= 0,
tableBordered: list.indexOf( \'table-bordered\' ) >= 0,
tableStriped: list.indexOf( \'table-striped\' ) >= 0,
} );
}
/* Then in the JSX:
<TextControl
label={ __( \'<table> classes\' ) }
type="text"
value={ tableClass }
onChange={ onChangeTableClass }
/>
*/
的默认值tableClass
属性应为table table-hover
因为默认值tableHover
州为true
.(只是一个建议)我想你应该attribute
作为source
对于tableClass
属性
是的,古腾堡进行区块验证validate 块的输出:
在编辑器初始化期间,使用从帖子内容解析的属性重新生成每个块的已保存标记。如果新生成的标记与post内容中已存储的标记不匹配,则该块将标记为无效。这是因为我们假设,除非用户进行编辑,否则标记应该与保存的内容保持一致。
因此,如果保存的标记是<p class="foo">bar baz</p>
, 但新生成的标记是<p class="foo new-class">bar baz</p>
, 然后你会得到一个错误。
因此,因为您正在更改输出,所以最好复制块,自定义它并将其注册为新块…
创建新块可能不像简单地扩展现有块那么容易,但新块比稍后必须处理块验证错误要好,例如在停用插件/主题之后
原因是您想更新;<table>
“类别”;每当选择/取消选择背景颜色时,需要修改PanelColorSettings
要素
其次,复制还允许您删除/重新排序现有节或向这些节添加新控件。
更新:关于tableHover: ! tableHover
或<attribute>: ! <attribute>
这相当于下面第四行在PHP中的作用:
<?php
$attrs = [ \'tableHover\' => false ];
$tableHover = $attrs[\'tableHover\']; // get the current value
$attrs[\'tableHover\'] = ! $tableHover; // toggle/change the value
var_dump( $tableHover, $attrs[\'tableHover\'] ); // bool(false) bool(true)
所以你(在评论中)问道:
我还是很困惑tableHover: ! tableHover
在…上onChange
. ... 为什么在设置属性时该属性被否定?
这是因为该属性是布尔类型,所以该值只能是true
或false
.
因此,如果当前值props.attributes
是true
, 然后tableHover: ! tableHover
将值切换/更改为false
.
// The currently saved block attributes.
const { tableHover } = props.attributes;
// When updating the tableHover, we could simply do:
props.setAttributes( { tableHover: ! tableHover } );
// .. which is equivalent to:
props.setAttributes( { tableHover: tableHover ? false : true } );
或在
onChange
回调时,可以使用作为第一个参数传递给回调的toggle控件元素的当前状态。
<ToggleControl
checked={ !! tableHover }
onChange={ ( checked ) => props.setAttributes( { tableHover: checked } ) }
/>
我想这更容易理解?:)
但是tableHover: ! tableHover
是一个更简单的版本,无需使用第一个onChange
参数
因此,只需使用您喜欢的任何方法,但请确保设置正确的值,例如,如果选中了切换控制元素,请设置tableHover
到true
.
顺便说一句,你也可以使用!!
用PHP代替(bool)
:
<?php
$foo = \'bar\';
var_dump( (bool) $foo, !! $foo ); // bool(true) bool(true)