如何在定制器的同一部分混合部分和完整页面刷新?

时间:2016-11-24 作者:Mark Kaplun

这真的是一个两阶段的问题,对于不太相关的背景,你可以看看这个问题-How to customize a shortcode using the customizer. 简而言之,我得到了一个小部件和一个短代码,它们实现了相同的功能,并通过将小部件生成的表单调整到customizer部分,在customizer中进行了自定义。

现在,我希望在可能的情况下使用部分刷新,但有些ssettings需要CSS和/或JS更改,必须进行完全刷新才能反映更改(如果您希望避免为此编写疯狂的JS代码)。

因此,问题中较简单的部分是“短代码”部分-如何在saame部分中有两个设置,一个进行部分刷新,另一个进行完整刷新。

高级部分是让它也能用于小部件。

为了让它不那么理论化,下面是有问题的代码-https://github.com/tiptoppress/category-posts-widget/tree/4.7.1

这是一种“最近发布的帖子”类型的小部件,允许您根据wp_query 设置,因此有些设置只需要访问服务器即可生成“预览”。其他一些设置通过插入CSS规则来控制显示,而其他一些设置-浏览器侧裁剪,需要JS来实现,每个小部件需要激活JS,为此,小部件的ID被排队。

Partials是wp_query 相关部分,但不适用于CSS。理论上,您可以将JS部分排队(我假设),但如何将其排队并不明显。

这里的问题并不是真的有可能破解一些可以让它工作的东西,因为只要付出足够的努力,一切都可以被调整到工作状态,问题是要以一种不会违反干燥和亲吻原则的方式来做,并向用户准确显示他将在前端看到什么,而不仅仅是一个近似值。在英语中,我不想分岔小部件前端的工作方式,这样我就可以声称我使用了partial,因为刷新和partial之间的实际用户用户体验差异并没有那么大,无法证明分岔前端代码的合理性。

(是的,这是一个两个问题合一的问题,但答案可能没有我想象的那么不同)

2 个回复
最合适的回答,由SO网友:Weston Ruter 整理而成

tl;dr 看见standalone example plugin 这演示了在选择性刷新请求将不同的脚本或样式排入队列时启动完全刷新,以及为选择性刷新的部分放置容器重新初始化JS行为。

我理解,目标是最大限度地减少自定义程序中所需的逻辑量,以预览对更新的分区的更改,这些分区根据设置更改将不同的脚本和样式排队。这里的解决方案已在定制器中的选择性刷新设计中考虑在内。特别是,当呈现分部时,它会在显示该分部的URL的上下文中进行呈现。这意味着在呈现部分时,为给定URL排队的所有脚本和样式都应该排队。为此customize_render_partials_before 操作包含以下文档:

Fires immediately before partials are rendered.

插件可以执行调用等操作wp_enqueue_scripts() 并收集可能在响应中排队的脚本和样式列表。

最终core可能会继续wp_enqueue_scripts() 默认情况下为自身。然而,对于选择性刷新的初始实现,排队是留给插件的。

脚本和样式排队后,需要与页面中的JS通信哪些资产已在响应中排队。这就是customize_render_partials_response 过滤器用于,如其文档所示:

Filters the response from rendering the partials.

插件可以使用此过滤器注入$scripts$styles, 它们是所呈现部分的依赖项。响应数据将通过render-partials-response JS事件,这样客户端就可以将脚本和样式插入DOM中,如果它们还没有在DOM中排队的话。

如果插件做到了这一点,那么它们需要处理任何这样做的脚本document.write() 并确保这些未被注入,否则将函数重写为no op,否则页面将被销毁。

插件应该知道$scripts$styles 最终可能默认包含在响应中。

已筛选的$response 数组通过render-partials-response 事件触发时间wp.customize.selectiveRefresh. 因此,要在选择性刷新请求将页面上尚未存在的资产排入队列时启动完全刷新,需要首先导出用于初始页面加载的已排入队列的脚本和样式的句柄,然后在render-partials-response JS事件检查在选择性刷新请求期间排队的脚本和样式句柄是否与最初在页面上排队的脚本和样式句柄相同。如果它们不同,那么JS只需要调用wp.customize.selectiveRefresh.requestFullRefresh(). 以下JS将仅在customizer预览中排队:

/* global wp, _ */
/* exported WPSE_247251 */
var WPSE_247251 = (function( api ) {

    var component = {
        data: {
            enqueued_styles: {},
            enqueued_scripts: {}
        }
    };

    /**
     * Init.
     *
     * @param {object} data Data exported from PHP.
     * @returns {void}
     */
    component.init = function init( data ) {
        if ( data ) {
            _.extend( component.data, data );
        }
        api.selectiveRefresh.bind( \'render-partials-response\', component.handleRenderPartialsResponse );
    };

    /**
     * Handle render-partials-response event, requesting full refresh if newly-enqueued styles/styles differ.
     *
     * @param {object} response Response.
     * @returns {void}
     */
    component.handleRenderPartialsResponse = function handleRenderPartialsResponse( response ) {
        if ( ! response.wpse_247251 ) {
            return;
        }
        if ( ! _.isEqual( component.data.enqueued_styles, response.wpse_247251.enqueued_styles ) ) {
            api.selectiveRefresh.requestFullRefresh();
        }
        if ( ! _.isEqual( component.data.enqueued_scripts, response.wpse_247251.enqueued_scripts ) ) {
            api.selectiveRefresh.requestFullRefresh();
        }
    };

    return component;
})( wp.customize );
可以在PHP中添加内联脚本以导出enqueued_scriptsenqueued_styles 然后呼叫WPSE_247251.init( data ).

当有选择地刷新部分时,需要更多的操作来确保重新初始化与容器关联的任何JS行为。具体地说,应该设计JS,以便有一个函数负责查找要在DOM中设置的元素。默认情况下,此函数应查看整个body. 但是,JS可以检查它是否在customizer预览的上下文中运行,如果是,请侦听partial-content-rendered 事件触发时间wp.customize.selectiveRefresh 然后调用传入的函数placement.container 作为初始化的范围,而不是整个body:

if ( \'undefined\' !== typeof wp && \'undefined\' !== typeof wp.customize && \'undefined\' !== typeof wp.customize.selectiveRefresh ) {
    wp.customize.selectiveRefresh.bind( \'partial-content-rendered\', function( placement ) {
        initializeAllElements( $( placement.container ) );
    } );
}
再次,请参见standalone example plugin 这演示了在选择性刷新请求将不同的脚本或样式排入队列时启动完全刷新,以及为选择性刷新的部分放置容器重新初始化JS行为。

最后,如果WordPress主题可以用React之类的东西实现,那么我们可以避免添加对页面上选择性刷新元素的特殊支持,因为状态的更改会自动导致DOM中所需的更改。由于我们还没有做到这一点(尽管正在为此开发原型),我们必须满足于下一个最佳体验,即以开发人员最小的额外努力快速刷新页面的各个部分:选择性刷新。

SO网友:prosti

我想对这个问题的某些部分补充一些说明。

马克对我的answer 注射对WordPress的反应。React已存在5年,相对稳定。“WestonRuter”中的这些词是我最喜欢的答案。

最后,如果WordPress主题可以用React之类的东西实现,那么我们可以避免添加对页面上选择性刷新元素的特殊支持,因为状态的更改会自动导致DOM中所需的更改。由于我们还没有做到这一点(尽管正在为此开发原型),我们必须满足于下一个最佳体验,即以开发人员最小的额外努力快速刷新页面的各个部分:选择性刷新。

为了达到可以实时预览(在预览窗格中)任何我们需要的JavaScript的阶段。React看起来是一个缺失的部分,但我们实际上需要在JavaScript中创建设置、控件、节和面板,并更新WordPress manager全局,这似乎很容易。

@韦斯顿·鲁特可以纠正我。

承诺:

亲吻(保持简单)并保持干燥(不要重复)

这里是我们所拥有的PHP类的一部分。

enter image description here

JavaScrpt中存在类似的模型,至少用于保存数据。

相关推荐