WordPress编辑器Gutenberg创建自定义Block模块

3月24日 · 2018年

在写这篇文章前,本来还在考虑写一个TinyMCE的教程,来自定义一个在后台编辑就可以所见即所得的模块功能。然而突然想到WordPress的新编辑器Gutenberg本身不就是以这样的目的来开发的吗?虽然Gutenberg现在还在测试阶段,但在今年晚些时候就将和WordPress5.0正式版一起上线。因此,就放弃了写TinyMCE教程的想法,直接上“如何创建Guntenberg自定义Block”的教程吧!

什么是Gutenberg

当你看到这篇文章时,无论WordPress是否已经更新到5.0,Gutenberg终将成为WordPress未来的编辑器。它是一个以JavaScript(React)(欢迎访问我的博客:http://panda.panda-studio.cn为驱动的编辑器,以“Block 模块”的形式,让用户在写文章时能更方便的自定义文章排版。

  • 截止文章发布时,WP5.0尚未发布,Gutenberg以插件的形式向旧版本提供测试和开发
  • 详见:WordPress官方介绍

要实现的功能

在开始这个教程前,先介绍最终要实现的效果:我想要实现的是一个Tips功能,将有4种类型的Tip,分辨是四种颜色。用户插入模块后,可以编辑自己输入的文字内容。在鼠标选定此模块时,将出现4个Tip类型选择器,分别是蓝色(info)、绿色(success)、橙色(worning)、红色(error)。点击相应的色彩按钮后,用户输入的文字内容(欢迎访问我的博客:http://panda.panda-studio.cn背景将变成对应的色彩。

实现此功能的原理:通过点击对应的色彩选择器,来修改class,从而改变tip的类型。如:class为“.tip.info”就显示蓝色、class为“.tip.success”就显示绿色。代码如下:

<div class="tips info">
    <p>蓝色效果示例</p>
</div>

<div class="tips success">
    <p>绿色效果示例</p>
</div>

效果示例:

开始创建

 

PHP部分

首先在主题的function.php中用注册需要的脚本、样式:

function register_pandastudio_tips() {
    wp_register_script(
        'pandastudio-tips',
        get_stylesheet_directory_uri().'/blocks/tips.js',
        array( 'wp-blocks', 'wp-element' )
    );

    wp_register_style(
        'pandastudio-tips',
        get_stylesheet_directory_uri().'/blocks/tips.css',
        array( 'wp-edit-blocks' )
    );

    register_block_type( 'pandastudio/tips', array(
        'editor_script' => 'pandastudio-tips',
        'editor_style'  => 'pandastudio-tips',
    ) );
}
if (function_exists('register_block_type')) {
    add_action( 'init', 'register_pandastudio_tips' );
}

在上面的代码中,将主题目录下的 tips.js 和 tips.css 引入到了Gutenberg编辑器中,由于WordPress5.0以前的版(欢迎访问我的博客:http://panda.panda-studio.cn本在未安装Gutenberg插件的状态没有注册block的方法(register_block_type),因此需要在添加action的时候先判断一下是否存在这个方法,否则在老版本的WordPress中会报错。

 

CSS部分

接下来是CSS样式,这里仅作示例,可以写任何你喜欢的样式:

.tip {
    background: #eef6fd;
    padding: 8px 20px !important;
    border-left-width: 3px !important;
    border-left-style: solid;
    border-left-color: #38a3fd;
    border-radius: 0 5px 5px 0 !important;
    margin: 0 0 10px 0 !important;
    box-shadow: none !important;
}

.tip p {
    margin: 5px 0 !important;
}

.tip:before {
    background: #38a3fd;
    border-radius: 50%;
    color: #fff;
    content: "i";
    font-family: "Dosis", "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;
    font-size: 16px;
    height: 21px;
    line-height: 21px;
    margin-left: -32px;
    margin-top: 5px;
    position: absolute;
    text-align: center;
    width: 21px;
}

.tip ol {
    margin: 0;
}

.tip.success {
    border-left-color: #86cc00;
    background: #f0f8e5;
}

.tip.success:before {
    background: #86cc00;
    content: "√";
}

.tip.worning {
    border-left-color: #ff7800;
    background: #fcf2e9;
}

.tip.worning:before {
    background: #ff7800;
    content: "!";
}

.tip.error {
    border-left-color: #ed0000;
    background: #fcf1f1;
}

.tip.error:before {
    background: #ed0000;
    content: "";
}

.tip.inlineBlock {
    display: inline-block;
}

.tip.error p {
    padding: 0 !important;
}

 

JavaScript(ES5)部分

接下来重点来了,由于Gutenberg是用JS驱动的,因此,最重要的是tip.js才对。先上代码,再做讲解:

var el = wp.element.createElement,
    registerBlockType = wp.blocks.registerBlockType,
    RichText = wp.blocks.RichText;

var el = wp.element.createElement,
    registerBlockType = wp.blocks.registerBlockType,
    RichText = wp.blocks.RichText;

registerBlockType('pandastudio/tips', {
    title: '提示框',
    icon: 'info',
    category: 'layout',
    attributes: {
        content: {
            type: 'array',
            source: 'children',
            selector: 'p',
        },
        typeClass: {
            source: 'attribute',
            selector: '.tip',
            attribute: 'class',
        }
    },
    edit: function(props) {
        var content = props.attributes.content,
            typeClass = props.attributes.typeClass || 'tip info',
            isSelected = props.isSelected;

        function onChangeContent(newContent) {
            props.setAttributes({ content: newContent });
        }

        function changeType(event) {
            var type = event.target.className;
            props.setAttributes({ typeClass: 'tip ' + type });
        }

        var richText = el(
            RichText, {
                tagName: 'p',
                onChange: onChangeContent,
                value: content,
                isSelected: props.isSelected,
                placeholder: '请输入...'
            });

        var outerHtml = el('div', { className: typeClass }, richText);

        var selector = el('div', { className: 'panda tipSelector' }, [
            el('button', { className: 'info', onClick: changeType }, '蓝色'),
            el('button', { className: 'success', onClick: changeType }, '绿色'),
            el('button', { className: 'worning', onClick: changeType }, '橙色'),
            el('button', { className: 'error', onClick: changeType }, '红色'),
        ])

        return el('div', {}, [outerHtml, isSelected && selector]);

    },

    save: function(props) {
        var content = props.attributes.content,
            typeClass = props.attributes.typeClass || 'tip info';

        var outerHtml = el('div', { className: typeClass }, el('p', {}, content));

        return el('div', {}, outerHtml);
    },
});

wp.element.createElement 是一个创建dom元素的方法,由于Gutenberg是基于React的,所以这实质上就是React的方法。由于我们写的是ES5的写法,所以才用得到。如果用JSX来写,然后再编译的话,就不需要了。

registerBlockType 是WordPress在Gutenberg中提供的创建块的方法,直接用就好。到本文发布为止,官方还没有关于此方法的详细文档(正式发布之后应该就有了)。

RichText 官方的说法是提供一个供用户编辑的输入框。类似于React的Controlled Componen(欢迎访问我的博客:http://panda.panda-studio.cnts。

registerBlockType的icon参数:图标可以任意从WordPress的Dashicons里面选择。

attributes 用于定义从保存的内容中(欢迎访问我的博客:http://panda.panda-studio.cn提取Block属性值的策略。提供了一种从保存的标记映射到Block的JS表示形式的方法

可以看到,edit和save是两个最复杂的参数,前者提供了在WordPress后台的Gutenberg中如何渲染和显示Block,后者提供了如何在WordPress中将Block存储和在前台显示。

Edit:

在这一个示例中,我创建了一个outerHtml来放置包含tips类型的div,内部的用户编写的内容则是用RichText创建的:

<div class="tips info">  <?-- 这是outerHtml -->
    <p>蓝色效果示例</p>    <?-- 这是RichText -->
</div>

并且创建了4个button按钮,在onClick点击时触发changeType事件,将按钮的class添加到outerHtml的class里面去。在edit最后return的时候通过isSelected来判断Block是否被用户选中,只有被选中的情况下,才显示Tips类型选择的4个button按钮。

SAVE:

保存和显示时候的状态就相对简单多了,只需要用创建dom的createElement方法创建出最终结果的html即可。

以上就是开发这样一个带有选项功能的Gutenberg Block的简单方式。由于大量运用了比较新的前端技术,因此WP开发者需要好好学习才可以跟上步伐咯。

由于全部代码全部已经展现在文章内容上,因此不提供示例代码下载。请直接复制粘贴即可参考

版权所有,禁止转载!

参考文档

 

5 条回应
验证码
输入运算符及数字使等式成立
{{comment.validate_num1}} = {{comment.validate_num2}}
点赞 确定
退出登录?
取消 确定
  1. Nicholas2018-8-16 · 15:44

    贵站主题非常精美!

  2. 有小安2018-5-11 · 3:09

    贵站主题非常精美!

  3. Tokin2018-4-10 · 10:34

    很早之前体验过这个编辑器,以为会和Dropbox的paper编辑器一样好用,实际上差距太大了。。不过比现在的可视化编辑器好用倒是真的。希望早日更新到5.0吧

    • Panda2018-4-10 · 22:07

      表示国内打不开Dropbox,好尴尬

  4. 异星空间2018-3-29 · 18:58

    感谢分享出来