title: "常见问题" post_status: publish comment_status: open taxonomy: category: - woocommerce post_tag: - Getting Started - Block Development - Repos
常见问题
本文档旨在解答一些来自扩展 WooCommerce Blocks 的开发者的常见问题。
我们会根据收到的问题不断更新此 FAQ 文档,这并非文档的最终版本。
如果您有此处未提及的问题,我们邀请您在 GitHub 讨论 或 WooCommerce 社区 Slack 上提出。
常见问题
如何响应购物车或结账的更改,例如配送方式选择或地址更改?
购物车和结账模块从 @wordpress/data 数据存储 读取所有数据。我们还提供了 WooCommerce Blocks 使用的数据存储的文档。
开发者通常希望响应购物车或结账中的更改。例如,当用户更改他们的配送方式或修改地址中的某一项时。
根据您的代码运行方式,有两种实现方法。
如果您的代码在 React 组件中运行
如果您的组件是购物车/结账模块的内部块,或者在 Slot/Fill 中渲染,您可以直接从相关的数据存储中选择所需的数据,并在数据发生变化时执行必要的操作。有关可用选择器的更多信息,请参阅 相关数据存储的文档。
/**
* 外部依赖
*/
import { useSelect } from '@wordpress/data';
import { cartStore } from '@woocommerce/block-data';
import { useEffect } from '@wordpress/element';
export const MyComponent = () => {
const { shippingAddress } = useSelect(
( select ) => select( cartStore ).getCartData(),
[]
);
useEffect( () => {
// 当 shippingAddress 发生变化时,执行某些操作
}, [ shippingAddress ] );
};
如果您的代码运行在非 React 环境中
如果您的代码没有进行任何 阻止 的 渲染,或者没有运行任何 React 代码,那么上述情况就成立。这意味着您将无法 访问 React 钩子 或自定义 钩子,例如 useSelect。 在这种情况下,您需要使用 useSelect 的非 钩子 替代方案,即 select。 考虑到需要响应变化,仅仅调用 select 是不够的,因为它只会运行一次。 您需要使用 subscribe 方法 来 订阅 您感兴趣的数据的变化。
/**
* 外部依赖
*/
import { select, subscribe } from '@wordpress/data';
import { cartStore } from '@woocommerce/block-data';
let previousCountry = '';
const unsubscribe = subscribe( () => {
const { shippingAddress } = select( cartStore ).getCartData();
if ( shippingAddress.country !== previousCountry ) {
previousCountry = shippingAddress.country;
// 当 `配送` 国家发生变化时,执行某些操作。
}
if ( /* 某些其他 `条件`,使得此 `订阅` 不再需要 */ ) {
unsubscribe();
}
}, cartStore );
由于 subscribe 回调函数会在数据 商店 接收到任何操作时运行,因此您需要使用 缓存 来避免在不需要时执行操作。 例如,如果您只想在国家发生变化时执行操作,则需要 缓存 之前的 价值,并在执行任务之前将其与 当前 价值 进行比较。
如果不再需要响应变化,您可以使用 unsubscribe 方法 从数据 商店 取消 订阅,该 方法 由 subscribe 方法 返回,如上面的示例所示。
购物车修改
如何从客户端动态地修改购物车内容?
要基于客户端操作在服务器上执行操作,您需要使用 extensionCartUpdate。
例如,要在您的网站上添加一个“如果您注册邮件列表,即可获得 10% 的折扣”的复选框,您可以使用 extensionCartUpdate 自动将 10% 的优惠券应用于购物车。
假设您已经添加了复选框,可以通过“附加结账字段 API”或创建内部块来实现,下一步是注册服务器端代码,以便在选中复选框时应用优惠券,反之则移除优惠券。
add_action('woocommerce_blocks_loaded', function() {
woocommerce_store_api_register_update_callback(
[
'namespace' => 'extension-unique-namespace',
'callback' => function( $data ) {
if ( isset( $data['checked'] ) && filter_var( $data['checked'], FILTER_VALIDATE_BOOLEAN ) === true ) {
WC()->cart->apply_coupon( 'mailing-list-10-percent-coupon' );
} else {
WC()->cart->remove_coupon( 'mailing-list-10-percent-coupon' );
}
}
]
);
} );
复选框的前端事件监听器代码如下所示:
const { extensionCartUpdate } = window.wc.blocksCheckout;
const onChange = ( checked ) => {
extensionCartUpdate(
{
namespace: 'extension-unique-namespace',
data: {
checked
}
}
)
}
要更改如何在订单摘要中的优惠券列表中显示此优惠券,可以使用 coupons 结账过滤器,如下所示:
const { registerCheckoutFilters } = window.wc.blocksCheckout;
const modifyCoupons = ( coupons, extensions, args ) => {
return coupons.map( ( coupon ) => {
if ( ! coupon.label === 'mailing-list-10-percent-coupon' ) {
return coupon;
}
return {
...coupon,
label: 'Mailing list discount',
};
} );
};
registerCheckoutFilters( 'extension-unique-namespace', {
coupons: modifyCoupons,
} );
如何在选择特定支付方式时,向购物车添加费用?
您需要在服务器端,根据所选的支付方式添加费用。这可以通过使用 woocommerce_cart_calculate_fees 动作来实现。
以下是用于添加费用的服务器端代码:
add_action(
'woocommerce_cart_calculate_fees',
function () {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
$chosen_payment_method_id = WC()->session->get( 'chosen_payment_method' );
$cart = WC()->cart;
if ( 'your-payment-method-slug' === $chosen_payment_method_id ) {
$percentage = 0.05;
$surcharge = ( $cart->cart_contents_total + $cart->shipping_total ) * $percentage;
$cart->add_fee( 'Payment method fee', $surcharge );
}
}
);
如何从服务器强制刷新购物车?
这可以通过使用 extensionCartUpdate 来实现,这是推荐的方法。 另一种方法是通过在有效的购物车对象上执行 wc/store/cart 数据存储中的 receiveCart 动作,如下所示:
const { dispatch } = window.wp.data;
dispatch( 'wc/store/cart' ).receiveCart( cartObject )
Store API 上的所有购物车路由都会返回一个购物车对象,可以用于此操作。 传递无效的购物车对象会导致块中出现错误。
您也可以使用:
const { dispatch } = window.wp.data;
dispatch('wc/store/cart').invalidateResolutionForStore()
但是,这会导致在获取新购物车时,短暂地显示一个空购物车。
如何在每个购物车项中渲染内容?
目前,这不是官方支持的功能。 但是,我们听说一些开发者通过使用 DOM 操作和 React portals 来实现这一点。 如果您选择采用此方法,请注意,如果我们在未来对购物车块进行更改,您的集成可能会停止工作。
结账修改
如何移除结账字段?
我们不建议这样做,因为 WordPress 和 Woo 支持大量的插件。 其中一些插件可能依赖于某些结账字段才能正常工作。 但是,如果您确定这些字段可以安全移除,请参阅 移除结账字段。
如何在结账过程中修改订单或客户数据?
如果您想修改在结账过程中提交的订单或客户数据,可以使用 woocommerce_store_api_checkout_order_processed 动作。
此动作在支付处理之前触发。 在此时,您可以像在 WooCommerce 生命周期中的任何其他时间一样修改订单,但您仍然需要调用 $order->save() 以保存更改。
例如,让我们确保用户的姓氏和名首字母大写:
add_action(
'woocommerce_store_api_checkout_order_processed',
function( WC_Order $order ) {
$order->set_shipping_first_name( ucfirst( $order->get_shipping_first_name() ) );
$order->set_shipping_last_name( ucfirst( $order->get_shipping_last_name() ) );
$order->set_billing_first_name( ucfirst( $order->get_billing_first_name() ) );
$order->set_billing_last_name( ucfirst( $order->get_billing_last_name() ) );
$order->save();
}
);
如何在结账块中渲染内容?
这取决于您想要渲染的内容。
渲染字段
在结账块中渲染字段的推荐方法是使用 额外的结账字段 API。
渲染自定义块
要在结账块中渲染自定义块,推荐的方法是创建一个现有结账内部块的子块。 我们有一个示例模板,可用于设置和研究内部块。 要安装和使用它,请按照 @woocommerce/extend-cart-checkout-block 中的说明进行操作。 请注意,此示例包含其他可扩展性的多个示例,而不仅仅是内部块。