是否可以(安全地)使用ES Next格式创建自定义块?

时间:2021-03-04 作者:Bagseye

我知道我的问题可能有点宽泛,甚至很容易回答。我一直在使用--es5 的标志@wordpress/create-block (https://developer.wordpress.org/block-editor/packages/packages-create-block/), 这在项目上相当成功。

使用此方法的原因是,在开发和发布后,通常需要对块进行许多更改,根据我过去(一年多前)的经验,ES Next方法在更改后立即有效地“杀死”块。因此,您必须遍历此块的每个实例并对其进行更改。

WP的开发人员是否为此提出了可行的解决方案,使开发人员能够在项目中安全地使用ES Next方法?我宁愿按照预期使用这些方法。自发布以来,文档一直不太好,所以我认为最好询问更广泛的社区。

为了更好地解释我的意思:

使用以下方法构建自定义块(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable/block.js) 在向后兼容性方面,--es5标志的属性似乎更稳定。如果要更改渲染模板(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable/index.php) 它不会打破障碍。

使用“反应”方法(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable-esnext/src/index.js), 在我过去的经验中,已经引起了一些问题。如果我使用此方法构建一个自定义块,并且对该块的代码进行了更改,则会“杀死”该块。据我所知,没有向后兼容性。

我想知道这是否只是自块编辑器首次引入以来实际解决的问题。或者继续构建自定义块的方法是使用ES5方法

One important bit I have missed out我最初暗示的是,我使用的是服务器端渲染块(请原谅我的术语,对于那些不熟悉它的人来说,这并不是一个明确的主题),它绕过了“更改块代码中的任何内容,您必须在编辑器中再次添加该块”的问题。不适合客户移交。

register_block_type( \'create-block/perk\', array(
    \'editor_script\'     => \'create-block-perk-block-editor\',
    \'editor_style\'      => \'create-block-perk-block-editor\',
    \'style\'             => \'create-block-perk-block\',
    \'render_callback\'   => \'perk_block_render\',
) );

function perk_block_render($attr, $content) {
$str = \'\';

if(isset($attr[\'mediaID\'])) {
    $mediaID = $attr[\'mediaID\'];

    $src = wp_get_attachment_image_src($mediaID, \'perk\');

    if($src && is_array($src) && isset($src[0])) {
        $srcset = wp_get_attachment_image_srcset($mediaID);
        $sizes = wp_get_attachment_image_sizes($mediaID, \'perk\');
        $alt = get_post_meta($mediaID, \'_wp_attachment_image_alt\', true);

        if(!$alt) {
            $alt = \'Perk icon\';
        }
    }
}

if(isset($attr[\'titleContent\'])) {
    $title = $attr[\'titleContent\'];
}

if(isset($attr[\'subContent\'])) {
    $subtitle = $attr[\'subContent\'];
}

$str = "<div class=\'perks__item animate\'>";
    if($mediaID) {
        $str .= "<img loading=\'lazy\' width=\'170\' height=\'170\' src=\'{$src[0]}\' alt=\'{$alt}\'/>";
    }

    if($title) {
        $str .= "<h2>{$title}</h2>";
    }

    if($subtitle) {
        $str .= "<p>{$subtitle}</p>";
    }

$str .= "</div>";

return $str;
}

我现在明白了,它与ES5/ESNext无关,然而,在查看了最近的视频后,似乎仍然存在使用WordPress的“首选”方法开发自定义块的问题。而且,使用服务器端渲染块来判断答案是唯一的出路。如果继续使用服务器端渲染块,代码是否会遇到问题?

2 个回复
SO网友:Jacob Peattie

无论您遇到什么问题,都会导致阻塞;“已终止”;编辑后与您概述的两种不同的块编写方法完全无关。

使用以下方法构建自定义块(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable/block.js)在向后兼容性方面,--es5标志的属性似乎更稳定。如果我要更改rendertemplate(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable/index.php)它不会打破障碍。

使用“反应”方法(https://github.com/WordPress/gutenberg-examples/blob/master/03-editable-esnext/src/index.js),在我过去的经验中,已经引起了一些问题。如果我使用此方法构建一个自定义块,并且对该块的代码进行了更改,则会“杀死”该块。我所说的没有向后兼容性。

这两种方法中的代码在所有意图和目的上都是相同的。它们只是使用了不同的语法。

“React”方法(实际上它们都是React)使用了一些较新的JavaScript特性,但这些只是编写在较新浏览器中工作的相同代码的更好方法。该方法还将JSX用于渲染函数。这只是编写这些函数的另一种方式,这些函数可以通过构建过程完全像第一个示例那样转换为函数。

您所描述的问题将是开发块的挑战,无论您使用哪种方法。保存使用块编辑器生成的帖子时,块的最终输出将以HTML形式保存到帖子内容中。当文章加载回编辑器时,您的块需要能够解析HTML并重建块数据,以便可以再次编辑。如果您的块在HTML发布后发生了更改,它可能无法执行此操作,并且将出现错误。这是预期的行为。

在不破坏现有帖子的情况下处理块更新的正确方法是“弃用”块。该过程的官方文档和代码示例如下here.

如果您在使用ESNext而不是ES5时遇到此问题,那么这很可能是巧合。这与你在做什么有关,而与你在用哪种方法有关,因为这种行为是块数据存储方式的结果,与用于编写块的JavaScript版本无关。

值得指出的是,对于块编辑器来说,这不是唯一的问题。如果我在任何系统中编写了一组代码,这些代码以某种格式处理数据,然后以改变格式的方式更新这些代码,我不能期望这些代码只会自动处理旧格式的数据。您需要将块输出的HTML视为一种格式,并相应地开发块。

SO网友:Sally CJ

我现在明白了,它与ES5/ESNext无关

是的,没错。

我同意雅各布在回答中所说的一切,但我特别想回答你问题的第三次修订,所以我决定写下这个答案,而不是通过评论来回答。

但在回应该修订之前,让我首先引用我在评论中最初所说的话:

即使使用ESNext方法,最终结果仍然是inES5,那么为什么使用ESNext是不安全的呢?但如果您在ESNext中构建,那么您需要运行build setup它将您的代码转换为ES5,以最大限度地兼容不同的浏览器。如果修改构建脚本(已转换为ES5的脚本),则需要确保不使用ESNext代码/语法,否则块很可能是;“已终止”;在不支持您使用的ESNext代码的浏览器上运行时。

其次,是的,关于下面的后一句话,你是对的:

ES Next方法在进行更改后立即有效地“终止”了块。因此,您必须遍历此块的每个实例并对其进行更改。

然而,这实际上是因为block validation 而不是使用ESNext或ES5-摘自块编辑器手册:

在编辑器初始化期间,使用从post\'scontent解析的属性,为每个块生成已保存的标记。如果新生成的标记与post内容中已存储的标记不匹配,则该块将标记为无效。这是因为我们假设,除非用户进行编辑,否则标记应该与保存的内容保持一致。

因此,对于您的3个rd问题的修订版:

在查看了最近的视频后,似乎使用WordPress的“首选”方法开发自定义块仍然是一个问题。

可能吧,但如果您经常更改块代码,那么您可能会首选带有服务器端生成的输出的动态块,而不是带有客户端生成的输出的非动态块。

如果继续使用服务器侧渲染块,代码是否会遇到问题?

从上述块验证的角度来看,没有,因为块编辑器手册says:

对于许多动态块save 回调函数应返回为null

当你回来的时候null, 编辑器将跳过块标记验证过程,避免频繁更改标记的问题。

如果您实际上没有经常更改块标记,那么正如另一个答案所说,您可以避免“更改块代码中的任何内容,并且您必须在编辑器中再次添加该块”(或块验证)问题,使用deprecated 所有物

摘自;How to preserve backward compatibility for a Block"E;在块编辑器手册中:

标记更改应限制在尽可能小的范围内,但如果一个锁需要更改其保存的标记,使以前的版本无效,则deprecated version应添加块的。

ESNext+JSX示例:

块的旧版本:

registerBlockType( \'my-blocks/foo-bar\', {
    title: \'Foo Bar\',
    icon: \'megaphone\',
    category: \'widgets\',

    attributes: {},
    save( props ) {
        return <p>foo bar</p>;
    },
} );
div 而不是p <我们更新了块以使用新的useBlockProps 钩住block API version 2 (WordPress 5.6+):

registerBlockType( \'my-blocks/foo-bar\', {
    apiVersion: 2,
    title: \'Foo Bar\',
    icon: \'megaphone\',
    category: \'widgets\',

    attributes: {},
    edit( props ) { // define \'edit\' so that the block is centered and clickable
        const blockProps = useBlockProps(); // here it\'s not useBlockProps.save()
        return <div { ...blockProps }>foo bar</div>;
    },
    save( props ) {
        const blockProps = useBlockProps.save();
        return <div { ...blockProps }>foo bar</div>;
    },

    deprecated: [ {
        attributes: {},
        save( props ) {
            return <p>foo bar</p>;
        },
    } ],
} );

附加说明

注册动态块时,应在两种PHP中定义块属性(使用register_block_type()) 和JavaScript(使用registerBlockType())。

否则,你会遇到这样的问题this.

相关推荐