使用 RefreshView API 刷新组件数据
不重载整页同步数据是关键的 UX 需求。RefreshView API 和 lightning/refresh 模块提供标准刷新机制——支持用户触发或应用调用。可精细控制刷新范围(刷新树),保持向后兼容。LDS 支持 RefreshView API,但自定义组件必须主动执行数据刷新(如 refreshApex() 或 refreshGraphQL())。
支持 LWS 和 Lightning Locker(协议格式不同)。Aura 基础组件暂不支持。由 LDS 管理的 wire 数据变更(如 @wire(getRecord))自动更新——不需 RefreshView API。
RefreshView API —— 用户体验与架构
用户触发的刷新流程(6步):① 组件显示触发刷新的按钮/控件;② 点击后派发 RefreshEvent;③ 最近的已注册容器组件接收事件(停止传播);④ 组件的刷新处理器启动刷新过程(可显示旋转器/日志);⑤ 后代组件通过 API 钩子参与刷新(获取 Salesforce 数据/同步);⑥ 所有数据同步完成→UI 更新。
应用触发的刷新:应用判断需要刷新(如会话过期后重新认证、移动端下拉刷新)→ 后续流程与用户触发相同。
架构三要素:RefreshEvent(信号事件)、refresh handler(参与者——注册回调方法)、refresh container(容器——接收事件并编排刷新过程)。容器和处理器组成刷新树(模拟 DOM 顺序——广度优先:父节点先于子节点)。
注册刷新处理器 —— 参与者组件
在 connectedCallback() 中注册,在 disconnectedCallback() 中注销。LWS 和 Locker 格式不同:
// LWS 启用时
connectedCallback() {
this.refreshHandlerID = registerRefreshHandler(this, this.refreshHandler);
}
disconnectedCallback() { unregisterRefreshHandler(this.refreshHandlerID); }
// Lightning Locker 时
this.refreshHandlerID = registerRefreshHandler(this.template.host, this.refreshHandler.bind(this));
// 处理器回调必须:
// ① 返回 Promise——true=继续向下处理子节点,false=阻止
// ② 执行必要的视图更新操作
// ③ 确保数据和状态重新同步
// ④ 显示适当 UI(spinner/toast)
refreshHandler() {
return new Promise((resolve) => {
fetch("https://api.example.com").then(() => resolve(true));
});
}
刷新树中注册的刷新方法按广度优先顺序从容器节点调用——高层(父)处理器先于低层(子)处理器完成。
发送刷新信号与注册容器
发送 RefreshEvent:任何组件可派发——从 lightning/refresh 导入:
import { RefreshEvent } from "lightning/refresh";
beginRefresh() { this.dispatchEvent(new RefreshEvent()); }
注册刷新容器(接收 RefreshEvent):在 connectedCallback() 中注册:
// LWS
this.refreshContainerID = registerRefreshContainer(this, this.refreshContainer);
// Locker
this.refreshContainerID = registerRefreshContainer(this.template.host, this.refreshContainer.bind(this));
// 容器回调接收 refreshPromise——resolve 时带 RefreshStatus 值
refreshContainer(refreshPromise) {
return refreshPromise.then((status) => {
if (status === REFRESH_COMPLETE) { /* Done! */ }
else if (status === REFRESH_COMPLETE_WITH_ERRORS) { /* 部分组件出错但仍完成 */ }
else if (status === REFRESH_ERROR) { /* 严重错误 */ }
});
}
RefreshEvent 遵循 DOM 事件冒泡规则——最近的注册祖先容器开始刷新过程。容器回调用于:记录开始/结束、显示旋转器、错误处理、Toast 通知。仅想参与刷新的组件注册处理器——后代必须自己注册回调。
注意事项与从 Apex 调用 API
使用 RefreshView API 的时机:处理 Aura 组件或第三方数据时。参与组件可用 notifyRecordUpdateAvailable() 或 refreshApex() 刷新 LDS 数据。仅需参与刷新的组件注册回调——组件不负责刷新后代(后代自己注册)。
从 Apex 调用 API:出于安全策略,Lightning 组件创建的会话默认无 API 访问权限——即使 Apex 代码也受限。使用命名凭据(Named Credential)绕过此限制——指定回调端点和认证参数。代码审查务必仔细——避免造成安全漏洞。优先检查是否可从 JavaScript 通过 LDS 调用——只有 LDS 不支持时才用 Apex + 命名凭据。
处理错误 —— 类型与生命周期
三种错误类型:
- JavaScript 错误:标准 Error 对象——
ReferenceError/SyntaxError等。同步代码中抛出→后续代码不执行。异步错误(Promise 回调中)传播方式不同——到浏览器控制台而非应用弹出框 - LDS 错误:wire adapter 返回
{ error: ... }——异步代码。 - Apex 错误:Apex 异常未处理时直接抛给客户端。
错误生命周期:未处理错误→抛给父组件→父组件也未处理→抛给外层应用(Lightning Experience/Experience Builder)→弹出 "A Component Error has occurred!"。异步错误:组件未处理→父组件→直接抛给浏览器控制台(不弹出)。
关键区别:同步错误 this.greeting = event.targets.value→应用弹出框。异步错误 Promise.resolve().then(() => { event.targets.value })→浏览器控制台。
显示与传播错误
显示错误:包含有帮助的纠正信息——一致性显示让用户知道预期。最常用方式——Toast 通知:
import { reduceErrors } from "c/ldsUtils";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
try { throw new Error("Something has gone wrong!"); } catch (e) {
this.dispatchEvent(new ShowToastEvent({
title: "Check your input", message: reduceErrors(e).join(", "), variant: "error",
}));
}
用自定义事件传播错误:多子组件→父组件统一处理的场景。子组件派发 new CustomEvent('error', { detail: 'Your custom error here' }) → 父组件 <c-child onerror={handleCustomError}> 处理。
错误信息源:可展示来自 LDS 的错误(wire error 属性)、来自 Apex 的错误(AuraHandledException 消息)、或自定义错误。参考 lwc-recipes errorPanel 和 ldsUtils 了解一致的错误处理模式。
感谢阅读本指南。如需继续学习,请参阅下一章:在 Salesforce 目标中使用组件。