Thủ thuật Website

Cách làm cho plugin của bạn tương thích với Gutenberg: Phần 2 (API thanh bên)

Nếu bạn đang cố gắng làm cho plugin của mình tương thích với Gutenberg, bạn có một số con đường có thể / nên thực hiện – tùy thuộc vào chức năng của plugin và cách nó cung cấp các tính năng cho người dùng.

Trong phần đầu tiên của loạt bài nhỏ này, chúng tôi đã khám phá API khối của Gutenberg – đây là thứ mà hầu hết các plugin cần về khả năng tương thích với Gutenberg. Lần này, chúng ta sẽ khám phá một phần khác của câu đố Gutenberg – API thanh bên của Gutenberg .

Chỉ để đảm bảo rằng chúng ta đang ở cùng một trang, hãy giải thích nhanh:

  • API khối của Gutenberg rất rộng rãi và cho phép bạn xây dựng hầu hết mọi thứ dưới dạng khối, nhưng đôi khi, điều đó là chưa đủ.
  • Mặt khác, API thanh bên cho phép các plugin đăng ký một thanh bên, nơi chúng có thể đưa chức năng của mình ra ngoài các khối. Thanh bên tương tự như Thanh tra khối.

Ví dụ: API thanh bên Gutenberg đang được sử dụng như được chứng minh bởi Yoast SEO:

Văn bản thay thế của hình ảnh

Bạn có thể sử dụng Sidebar API ở đâu?

Gần đây, chúng tôi đã làm việc để làm cho plugin của mình – WP Product Review – sẵn sàng cho Gutenberg. WP Product Review đã sử dụng các trường meta để thêm dữ liệu đánh giá vào bài đăng và chúng tôi không thể chuyển thành một khối vì nhiều lý do tương thích ngược. Do đó, chúng tôi đã sử dụng API thanh bên.

Đây là khối của plugin trong trình chỉnh sửa cổ điển:

Văn bản thay thế của hình ảnh

Khi người dùng cho biết rằng bài đăng là một bài đánh giá có nút chuyển đổi thanh bên, họ sẽ có thể định cấu hình mọi thứ về hộp đánh giá của mình từ các tùy chọn thanh bên.

WP Product Review là một trong những ví dụ mà Sidebar API có thể hữu ích. Một ví dụ tuyệt vời khác là plugin Drop It , cho phép người dùng chèn ảnh stock từ Unsplash và Giphy bằng cách sử dụng thanh bên.

Trong bài đăng này, tôi sẽ hướng dẫn bạn quy trình triển khai một cái gì đó tương tự và làm cho plugin của bạn tương thích với Gutenberg thông qua API Sidebar.

Các hộp meta đã sẵn sàng cho Gutenberg theo mặc định, nhưng không hoàn toàn

Hãy bắt đầu với các hộp meta. Hãy sử dụng một plugin sử dụng một hộp meta đơn giản để cung cấp một số chức năng cho người dùng trên màn hình trình chỉnh sửa.

Điều này có thể giống như sau trong Trình chỉnh sửa cổ điển:

Văn bản thay thế của hình ảnh

Bạn có thể sử dụng mã sau để tạo một hộp meta như vậy – nó cũng có sẵn trong kho lưu trữ Hello Gutenberg :

/**
 * Register Hello Gutenbert Meta Box
 */
function hello_gutenberg_add_meta_box() {
    add_meta_box( 'hello_gutenberg_meta_box', __( 'Hello Gutenberg Meta Box', 'hello-gutenberg' ), 'hello_gutenberg_metabox_callback', 'post' );
}
add_action( 'add_meta_boxes', 'hello_gutenberg_add_meta_box' );

/**
 * Hello Gutenberg Metabox Callback
 */
function hello_gutenberg_metabox_callback( $post ) {
    $value = get_post_meta( $post->ID, '_hello_gutenberg_field', true );
    ?>
    <label for="hello_gutenberg_field"><?php _e( 'What\'s your name?', 'hello-gutenberg' ) ?></label>
    <input type="text" name="hello_gutenberg_field" id="hello_gutenberg_field" value="<?php echo $value ?>" />
    <?php
}

/**
 * Save Hello Gutenberg Metabox
 */
function hello_gutenberg_save_postdata( $post_id ) {
    if ( array_key_exists( 'hello_gutenberg_field', $_POST ) ) {
        update_post_meta( $post_id, '_hello_gutenberg_field', $_POST['hello_gutenberg_field'] );
    }
}
add_action( 'save_post', 'hello_gutenberg_save_postdata' );

Vì vậy, câu hỏi cần đặt ra ở đây là:

Chúng ta có cần làm cho nó tương thích với Gutenberg ngay từ đầu không?

Tại thời điểm này, chúng ta nên cân nhắc tự hỏi bản thân rằng Gutenberg tương thích là gì. Ví dụ: nếu bạn sử dụng hộp meta này trong Gutenberg mà không thực hiện bất kỳ thay đổi nào đối với nó, nó sẽ vẫn hoạt động.

Tuy nhiên, khi chúng ta nói về khả năng tương thích của Gutenberg, chúng ta không chỉ nói về plugin hoạt động trong môi trường Gutenberg, mà là plugin hoạt động giống như Gutenberg .

“Tại sao?” – bạn sẽ hỏi. Rất đơn giản, những người dùng sẽ bắt đầu sử dụng WordPress sau khi Gutenberg là trình chỉnh sửa mặc định sẽ thấy các cách cũ trở nên phản trực quan. Hơn nữa, họ sẽ mong đợi một phong cách giống Gutenberg hơn cho mọi thứ trong trình chỉnh sửa.

Nếu bạn không cung cấp cho người dùng cảm giác bản địa, họ chắc chắn sẽ tìm kiếm các giải pháp thay thế sẽ hoạt động tốt hơn với Gutenberg.

Cuối cùng, chúng ta hãy làm bẩn tay với một số mã!

Bắt đầu với API thanh bên

Chúng tôi sẽ bắt đầu viết mã Sidebar của chúng tôi trong Gutenberg để đưa vào trường meta của chúng tôi. Bạn có thể tiếp tục sử dụng kho lưu trữ Gutenberg Boilerplate làm điểm bắt đầu.

Chuẩn bị hộp meta của bạn sẵn sàng cho Gutenberg

Trước khi bắt đầu, trước tiên chúng ta cần nói với Gutenberg rằng chúng ta sẽ không sử dụng hộp meta của mình trong Gutenberg. Bạn có thể làm điều đó bằng cách chuyển đối số __ back_compat_meta_box vào hàm add_meta_box , như sau:

/**
 * Register Hello Gutenberg Metabox
 */
function hello_gutenberg_add_meta_box() {
    add_meta_box( 'hello_gutenberg_meta_box', __( 'Hello Gutenberg Meta Box', 'hello-gutenberg' ), 'hello_gutenberg_metabox_callback', 'post',  array(
        '__back_compat_meta_box' => false,
    ) );
}
add_action( 'add_meta_boxes', 'hello_gutenberg_add_meta_box' );

Sổ tay Gutenberg có thêm chi tiết về cách bạn có thể xử lý chuyển các hộp meta PHP sang Gutenberg ( tại đây ).

Điều này sẽ đảm bảo rằng các hộp meta PHP cũ của chúng tôi không xuất hiện trong Gutenberg nữa. Bây giờ chúng ta cũng cần chuẩn bị cho trường meta của mình sẵn sàng cho Gutenberg bằng cách thêm nó vào WordPress REST API. Bạn có thể thêm mã sau để đăng ký trường meta với REST API:

/**
 * Register Hello Gutenberg Meta Field to Rest API
 */
function hello_gutenberg_register_meta() {
    register_meta(
        'post', '_hello_gutenberg_field', array(
            'type'      => 'string',
            'single'    => true,
            'show_in_rest'  => true,
        )
    );
}
add_action( 'init', 'hello_gutenberg_register_meta' );

Thao tác này sẽ thêm _ hello_gutenberg_field vào đối tượng meta trong API REST.

Hàm này sẽ chỉ thực hiện công việc hiển thị giá trị của chúng ta trong API REST. Bây giờ chúng ta cũng cần thêm một phương thức để cập nhật trường meta của mình bằng cách sử dụng API REST.

Đoạn mã sau sẽ thêm tuyến tùy chỉnh của chúng tôi vào WordPress REST API, sẽ là / hello-gutenberg / v1 / update-meta / :

/**
 * Register Hello Gutenberg Metabox to Rest API
 */
function hello_gutenberg_api_posts_meta_field() {
    register_rest_route(
        'hello-gutenberg/v1', '/update-meta', array(
            'methods'  => 'POST',
            'callback' => 'hello_gutenberg_update_callback',
            'args'   => array(
                'id' => array(
                    'sanitize_callback' => 'absint',
                ),
            ),
        )
    );
}
add_action( 'rest_api_init', 'hello_gutenberg_api_posts_meta_field' );

/**
 * Hello Gutenberg REST API Callback for Gutenberg
 */
function hello_gutenberg_update_callback( $data ) {
    return update_post_meta( $data['id'], $data['key'], $data['value'] );

Tuyến API REST này sẽ được sử dụng để sửa đổi trường meta của chúng tôi từ thanh bên Gutenberg. Bạn có thể tìm hiểu thêm về WordPress REST API và cách đăng ký các tuyến tùy chỉnh từ đây .

Tương tự, nếu bạn muốn biết WordPress REST API là gì và cách bắt đầu, bạn có thể đọc bài đăng trên blog của chúng tôi: WordPress REST API: Nó là gì và cách bắt đầu sử dụng nó .

Thêm khối thanh bên vào Gutenberg

Hãy bắt đầu với mã Sidebar từ Gutenberg Boilerplate :

/**
 * Internal block libraries
 */
const { __ } = wp.i18n;

const { Fragment } = wp.element;

const {
    PluginSidebar,
    PluginSidebarMoreMenuItem,
} = wp.editPost;

const { registerPlugin } = wp.plugins;

const Component = () => (
    <Fragment>
        <PluginSidebarMoreMenuItem
            target="gutenberg-boilerplate-sidebar"
        >
            { __( 'Gutenberg Boilerplate' ) }
        </PluginSidebarMoreMenuItem>
        <PluginSidebar
            name="gutenberg-boilerplate-sidebar"
            title={ __( 'Gutenberg Boilerplate' ) }
        >
            <h2>{ __( 'Hello World!' ) }</h2>
        </PluginSidebar>
    </Fragment>
);

registerPlugin( 'gutenberg-boilerplate', {
    icon: 'admin-site',
    render: Component,
} );

Thao tác này sẽ chèn một thanh bên rất đơn giản vào trình soạn thảo Gutenberg. Chúng tôi sẽ coi đây là điểm khởi đầu và xây dựng dự án của mình dựa trên nó.

Mã ví dụ là từ kho lưu trữ Gutenberg Boilerplate của chúng tôi và do đó, chúng tôi cần thay thế tất cả các lần xuất hiện của “Gutenberg Boilerplate” bằng “Hello Gutenberg”.

Các thành phần được sử dụng

Trong khi thanh bên của chúng tôi đã nhập nhiều thành phần, chúng tôi sẽ cần nhiều hơn nữa. Bạn có thể thay thế phần trên cùng của mã bằng phần sau:

/**
 * Internal block libraries
 */

const { __ } = wp.i18n;

const {
    PluginSidebar,
    PluginSidebarMoreMenuItem
} = wp.editPost;

const {
    PanelBody,
    TextControl
} = wp.components;

const {
    Component,
    Fragment
} = wp.element;

const { withSelect } = wp.data;

const { registerPlugin } = wp.plugins;

Chúng ta hãy tìm hiểu nhanh về tất cả các thành phần mà chúng tôi đã nhập khẩu.

  • Như đã thảo luận trong phần trước, thành phần __ được sử dụng để làm cho văn bản của chúng ta có thể dịch được.
  • Thành phần PluginSidebar được sử dụng để thêm thanh bên của chúng tôi vào Gutenberg. PluginSidebarMoreMenuItem được sử dụng để thêm một nút vào menu Gutenberg, nút này sẽ bật tắt khả năng hiển thị của thanh bên.
  • Thành phần PanelBody được sử dụng để thêm một bảng điều khiển vào thanh bên của chúng tôi.
  • TextControl được sử dụng cho trường đầu vào của chúng tôi.
  • Sau đó, chúng tôi nhập các thành phần Component và Fragment . Cả hai đều là các thành phần React mà chúng tôi sử dụng trong thanh bên của mình. Thành phần Fragment được sử dụng để nhóm một danh sách con mà không cần thêm các nút phụ vào DOM. Chúng ta cần sử dụng thành phần Fragment trong mã của mình vì JSX không cho phép chúng ta có nhiều hơn một nút cha.
  • withSelect là một thành phần bậc cao hơn. Để tìm hiểu các thành phần bậc cao là gì, tôi khuyên bạn nên đọc tài liệu này .
  • Và cuối cùng, chúng ta nhập registerPlugin , nó tương tự như registerBlockType mà chúng ta đã sử dụng trong bài viết trước . Thay vì đăng ký một khối, registerPlugin đăng ký plugin của bạn.

Thêm điều khiển

Cho đến nay thanh bên của chúng tôi chỉ là một hàm Thành phần, nhưng vì chúng tôi sẽ sử dụng các phương thức vòng đời của React , chúng tôi sẽ biến nó thành một thành phần React, như sau:

class Hello_Gutenberg extends Component {
    render() {
        return (
            <Fragment>
                <PluginSidebarMoreMenuItem
                    target="hello-gutenberg-sidebar"
                >
                    { __( 'Hello Gutenberg' ) }
                </PluginSidebarMoreMenuItem>
                <PluginSidebar
                    name="hello-gutenberg-sidebar"
                    title={ __( 'Hello Gutenberg' ) }
                >
                    <h2>{ __( 'Hello World!' ) }</h2>
                </PluginSidebar>
            </Fragment>
        )
    }
}

registerPlugin( 'hello-gutenberg', {
    icon: 'admin-site',
    render: Hello_Gutenberg,
} );

Điều này sẽ làm cho thanh bên của bạn hoạt động với văn bản thuần túy.

Bây giờ, hãy thêm trường của chúng ta vào thanh bên. Nó sẽ làm cho thành phần của chúng ta trông như thế này:

class Hello_Gutenberg extends Component {
    render() {
        return (
            <Fragment>
            <PluginSidebarMoreMenuItem
                target="hello-gutenberg-sidebar"
            >
                { __( 'Hello Gutenberg' ) }
            </PluginSidebarMoreMenuItem>
            <PluginSidebar
                name="hello-gutenberg-sidebar"
                title={ __( 'Hello Gutenberg' ) }
            >
                <PanelBody>
                    <TextControl
                        label={ __( 'What\'s your name?' ) }
                        // value={}
                        // onChange={}
                    />
                </PanelBody>
            </PluginSidebar>
        </Fragment>
        )
    }
}

Thao tác này sẽ thêm một trường nhập đơn giản vào thanh bên mà sẽ hoàn toàn không làm gì vào thời điểm này.
Bây giờ chúng ta còn hai nhiệm vụ:

  • Hiển thị giá trị của trường meta của chúng tôi.
  • Cho phép cập nhật giá trị của trường meta của chúng tôi từ thanh bên.

Văn bản thay thế của hình ảnh

Hiển thị giá trị meta

Để tìm nạp dữ liệu meta, chúng tôi sẽ sử dụng wp.apiFetch . apiFetch là một thư viện tiện ích cho phép chúng tôi thực hiện các yêu cầu API REST.

Chúng tôi sẽ sử dụng apiFetch trong phương thức khởi tạo của thành phần React của chúng tôi, như sau:

class Hello_Gutenberg extends Component {
    constructor() {
        super( ...arguments );

        this.state = {
            key: '_hello_gutenberg_field',
            value: '',
        }

        wp.apiFetch( { path: `/wp/v2/posts/${this.props.postId}`, method: 'GET' } ).then(
            ( data ) => {
                this.setState( { 
                    value: data.meta._hello_gutenberg_field
                } );
                return data;
            },
            ( err ) => {
                return err;
            }
        );
    }

    render() {
        return (
            <Fragment>
            <PluginSidebarMoreMenuItem
                target="hello-gutenberg-sidebar"
            >
                { __( 'Hello Gutenberg' ) }
            </PluginSidebarMoreMenuItem>
            <PluginSidebar
                name="hello-gutenberg-sidebar"
                title={ __( 'Hello Gutenberg' ) }
            >
                <PanelBody>
                    <TextControl
                        label={ __( 'What\'s your name?' ) }
                        value={ this.state.value }
                        // onChange={}
                    />
                </PanelBody>
            </PluginSidebar>
        </Fragment>
        )
    }
}

Đầu tiên, chúng tôi đã xác định một trạng thái ban đầu, về cơ bản là khóa và giá trị của trường meta của chúng tôi. Sau đó, chúng tôi đang sử dụng apiFetch để tìm nạp dữ liệu từ bài đăng hiện tại của chúng tôi.

Chúng tôi đang chuyển ID của bài đăng hiện tại của chúng tôi với biến $ {this.props.postId} . Chúng ta sẽ trở lại thời điểm này sau.

Sau khi dữ liệu được tìm nạp, chúng tôi cập nhật trạng thái của mình với giá trị từ API REST của chúng tôi.

Bây giờ, hãy quay lại biến postId. Chúng tôi hiện không biết ID của bài đăng hiện tại của mình, vì vậy, chúng tôi sử dụng thành phần cấp cao hơn withSelect , như sau:

const HOC = withSelect( ( select ) => {
    const { getCurrentPostId } = select( 'core/editor' );
    return {
        postId: getCurrentPostId(),
    };
} )( Hello_Gutenberg );

registerPlugin( 'hello-gutenberg', {
    icon: 'admin-site',
    render: HOC,
} );

Điều này sẽ chuyển ID của bài đăng hiện tại của chúng tôi dưới dạng biến postId . Bây giờ bạn có thể chạy một bài đăng cũ hơn và thanh bên Gutenberg của chúng tôi sẽ hiển thị giá trị của trường meta của bạn.

Cập nhật giá trị meta

Bây giờ chúng ta cần cho phép thanh bên của mình cũng cập nhật giá trị meta. Tương tự như tìm nạp các chi tiết, chúng ta sẽ sử dụng tiện ích wp.apiRequest .

Mỗi khi giá trị của trạng thái của chúng tôi thay đổi, chúng tôi sẽ cập nhật nó bằng API REST. Đối với điều này, trước tiên chúng ta cần thêm một sự kiện onChange vào TextControl của chúng ta , như sau:

<TextControl
    label={ __( 'What\'s your name?' ) }
    value={ this.state.value }
    onChange={ ( value ) => { 
        this.setState( {
            value
        } );
    } }
/>

Và sau đó, chúng tôi sẽ sử dụng phương thức vòng đời getDerivedStateFromProps để gửi yêu cầu REST của chúng tôi.

Bạn có thể thêm mã sau vào bên dưới hàm tạo của mình:

static getDerivedStateFromProps( nextProps, state ) {
    wp.apiRequest( { path: `/hello-gutenberg/v1/update-meta?id=${nextProps.postId}`, method: 'POST', data: state } ).then(
        ( data ) => {
            return data;
        },
        ( err ) => {
            return err;
        }
    );
}

Điều này sẽ cập nhật trường meta của chúng tôi mỗi khi chúng tôi thay đổi nó từ trường. Bây giờ bạn sẽ thấy một vấn đề với cách tiếp cận này.

Các giá trị meta sẽ được cập nhật mỗi khi bạn thay đổi giá trị meta, có hai vấn đề với cách tiếp cận này:

  • Dữ liệu của bạn sẽ được lưu ngay cả khi bạn quyết định không cập nhật bài đăng.
  • Nó sẽ thực hiện một cuộc gọi HTTP quá thường xuyên, điều này không lý tưởng.

Dữ liệu chỉ nên được lưu khi bạn lưu hoặc xuất bản bài đăng. Đối với điều này, chúng tôi có thể sử dụng thành phần cấp cao hơn của chúng tôi để tìm hiểu khi nào bài đăng đang được lưu.

Bạn có thể thay thế hàm HOC của chúng tôi bằng mã sau:

const HOC = withSelect( ( select, { forceIsSaving } ) => {
    const {
        getCurrentPostId,
        isSavingPost,
        isPublishingPost,
        isAutosavingPost,
    } = select( 'core/editor' );
    return {
        postId: getCurrentPostId(),
        isSaving: forceIsSaving || isSavingPost(),
        isAutoSaving: isAutosavingPost(),
        isPublishing: isPublishingPost(),
    };
} )( Hello_Gutenberg );

Điều này sẽ cung cấp cho chúng tôi một số biến mà chúng tôi có thể sử dụng để kiểm tra xem bài đăng của chúng tôi đang được lưu hoặc xuất bản.

Chúng tôi cần thêm điều kiện này vào chức năng yêu cầu bài đăng của chúng tôi:

static getDerivedStateFromProps( nextProps, state ) {
    if ( ( nextProps.isPublishing || nextProps.isSaving ) && !nextProps.isAutoSaving ) {
        wp.apiRequest( { path: `/hello-gutenberg/v1/update-meta?id=${nextProps.postId}`, method: 'POST', data: state } ).then(
            ( data ) => {
                return data;
            },
            ( err ) => {
                return err;
            }
        );
    }
}

Giờ đây, các giá trị meta sẽ chỉ cập nhật khi chúng tôi lưu, cập nhật hoặc xuất bản bài đăng.
Đó là nó! Thanh bên của bạn hiện đã hoàn tất và bạn vừa học cách làm cho plugin của mình tương thích với Gutenberg!

Bạn có thể kiểm tra khối của mình để đảm bảo rằng nó hoạt động. Nếu không, vui lòng để lại câu trả lời của bạn trong phần bình luận bên dưới, và tôi sẽ cố gắng giúp bạn.

Điều gì tiếp theo khi bạn hoàn thành với API thanh bên?

Bạn có thể tìm thấy ví dụ đã hoàn thành trong kho lưu trữ Hello Gutenberg . Nếu bạn tìm thấy bất kỳ vấn đề nào, vui lòng mở một vấn đề .

Một lần nữa, đây là một ví dụ nhỏ về những gì có thể với API thanh bên của Gutenberg. Có rất nhiều điều tuyệt vời mà bạn có thể tạo ra với Gutenberg và các API của nó.

Bạn đang cố gắng đạt được điều gì với Gutenberg? Hãy cho chúng tôi biết.

Related Articles

Trả lời

Email của bạn sẽ không được hiển thị công khai.

Back to top button