Dynamic Block - Как создать динамическую таблицу стилей при сохранении/загрузке после публикации

Я создал рабочий блок Гутенберга с помощью Create Guten Block (https://github.com/ahmadawais/create-guten-block). В настоящее время он работает только со встроенными стилями, но по требованию я должен их избегать.

Поэтому я хочу создать таблицу стилей поста/страницы при сохранении поста, включая настройки стиля для моих блоков (например, цвет фона, цвет, размер шрифта...)

Текущая функция сохранения моего блока (block.js)

save: function( props ) {
        const { attributes: { typetext, infotext, linktext, background_color, background_button_color, text_color, text_color_button }} = props;
        return (
            <div id="cgb-infoblock" className="cgb-infoblock">
                <div className="cgb-infoblock-body" style={{
                    backgroundColor: background_color,
                    color: text_color,
                }}>
                    <div className="cgb-infoblock-type">
                        <p>
                            <span className="cgb-infoblock-icon"><i>i</i></span>
                            { typetext && !! typetext.length && (
                                <RichText.Content
                                    tagName="span"
                                    className={ classnames(
                                        'cgb-infoblock-type-text'
                                    ) }
                                    style={ {
                                        color: text_color
                                    } }
                                    value={ typetext }
                                />
                            )}
                        </p>
                    </div>
                    <div className="cgb-infoblock-text">
                        { infotext && !! infotext.length && (
                            <RichText.Content
                                tagName="p"
                                style={ {
                                    color: text_color
                                } }
                                value={ infotext }
                            />
                        )}
                    </div>
                </div>
                <div className="cgb-infoblock-button" style={{
                    backgroundColor: background_button_color,
                    color: text_color_button,
                }}>
                    { linktext && !! linktext.length && (
                        <RichText.Content
                            tagName="p"
                            style={ {
                                color: text_color_button
                            } }
                            value={ linktext }
                        />
                    )}
                </div>
            </div>
        );
    },

Лучшим решением будет генерация таблицы стилей для целой страницы/поста со всеми настройками из всех блоков.

Лучше всего было бы, если бы генерация таблицы стилей происходила при сохранении страницы, но также было бы нормально, если бы это происходило при загрузке страницы. Поскольку эти посты не будут большими, производительность не должна быть большой проблемой.


person Hoargarth    schedule 19.06.2019    source источник
comment
вам действительно нужно создать таблицу стилей, например, создать файл filename.css? Или будет достаточно, если компонент имеет определенный стиль, зависящий от атрибутов блоков?   -  person niklas    schedule 20.06.2019
comment
@niklas да, я хочу имя файла.css; Было бы даже нормально, если бы он генерировался каждый раз, когда кто-то посещает страницу. (знаю, не очень хорошо для производительности)   -  person Hoargarth    schedule 21.06.2019
comment
откуда берется требование избегать встроенных стилей. Это может оказаться более производительным, чем загрузка новой таблицы стилей.   -  person niklas    schedule 21.06.2019


Ответы (1)


Итак, покопавшись, я понял это сам. На всякий случай, если у кого-то еще возникла эта проблема, вот решение:

Прежде всего, атрибуты должны быть определены в registerBlockTypefunction.

registerBlockType( 'cgb/your-block-type', {
title: __( 'Your Block Name' ),
icon: 'shield',
category: 'maybe-a-category',
keywords: [
    __( 'some keywords' ),
],

attributes: {
    background_color: {
        type: 'string',
        default: 'default' //we will use the "default"-value later
    },
},

Итак, теперь Wordpress знает, какие атрибуты вы хотите сохранить. Проблема теперь, пока значение «по умолчанию» не перезаписано, Wordpress не сохранит значение в атрибутах объекта блока. Чтобы решить эту проблему, мы будем использовать функцию save из registerBlockType. (Небольшое примечание: это не приведет к срабатыванию значения по умолчанию для виджета редактора, поэтому вам всегда нужно изменить значение вашего background_color, чтобы увидеть его при первой вставке виджета в редактор Гутенберга. Чтобы исправить это, используйте saveDefaultValue(this.props) прямо в начало вашей функции render().)

    save: function( props ) {

    saveDefaultValues(props);

    const { attributes: {background_color}} = props;
    return (
        //... here's your html that's beeing saved
    );
},

function saveDefaultValues(props) {
    if(props.attributes.background_color === 'default'){
        props.attributes.background_color = '#f1f6fb';
    }
}

При этом мы заставляем WordPress сохранять наше значение по умолчанию. Почти уверен, что для этого есть лучшее решение, но, поскольку я только начал с реакции/Гутенберга, это единственное, что заставило меня работать.

Хорошо, теперь мы можем сохранить наши атрибуты в блочном объекте. Теперь мы хотим создать нашу динамическую таблицу стилей. Для этого мы создаем новый файл .php в следующем каталоге /plugin-dir/src/, так как мы используем create-guten-block. Имя не имеет значения, но я назвал его так же, как и свою таблицу стилей. `gutenberg-styles.css.php``

Позже gutenberg-styles.css.php будет создавать gutenberg-styles.cssфайл каждый раз, когда кто-то посещает пост. Но сначала мы смотрим в файл plugin.phpfile. Добавьте следующий код:

function create_dynamic_gutenberg_stylesheet() {
    global $post;
    require_once plugin_dir_path( __FILE__ ) . 'src/gutenberg-styles.css.php';

    wp_enqueue_style('cgb/gutenberg-styles', plugins_url( 'src/gutenberg-styles.css',  __FILE__ ));
}
add_action('wp_head', 'create_dynamic_gutenberg_stylesheet', 5, 0);

Этот код обращается к переменной global $post, она нам нужна, чтобы получить все гутенберг-блоки из текущего посещенного поста. После этого нам потребуется наш собственный gutenberg-styles.css.php, который автоматически создаст нашу таблицу стилей, которая будет помещена в очередь в следующей строке. Теперь подключите его к wp_head (вы, вероятно, могли бы также подключить его к действию сохранения WordPress, но вам придется проделать больше работы для постановки таблицы стилей в очередь)

Наконец взглянем на наш gutenberg-styles.css.php:

$styleSheetPath = plugin_dir_path( __FILE__ ) . 'gutenberg-styles.css';
$styleSheet = '';
$blocks = parse_blocks($post->post_content);

//loop over all blocks and create styles
foreach($blocks as $block) {
    $blockType = $block['blockName'];
    $blockAttributes = $block['attrs']; //these are the attributes we've forced to saved in our block's save function

    //switch case so you can target different blocks
    switch ($blockType) {
    case 'cgb/your-block-type':
        $styleSheet .= '.your-block-class {'.PHP_EOL
        $styleSheet .= 'background-color: '.$blockAttributes['background_color'].';'.PHP_EOL
        $styleSheet .= '}'.PHP_EOL
        break;
    }
}

file_put_contents($styleSheetPath, $styleSheet); //write css styles to stylesheet (creates file if it not exists)

Я добавил PHP_EOL в каждую строку для создания разрывов строк, вам не нужно этого делать. Но теперь вы можете посетить страницу с вашим пользовательским блоком и увидеть, что gutenberg-styles.css загружается и применяется к вашим блокам.

person Hoargarth    schedule 24.06.2019