DEX475

Refresh Component Data with RefreshView API

课程介绍

各位同学,现在我们来聊聊 ,RefreshView API, 和 ,lightning/refresh, 这个模块。 那它到底是干嘛用的呢?简单来说,就是给你一种标准的方法,,在不重新加载整个页面的情况下,只刷新组件里的数据,。比如你做了一个列表,用户点了一下“刷新”按钮,你肯定不想让整个页面“轰”一下重新加载,那样体验很差。RefreshView 就是专门解决这种局部数据刷新的。 它支持两种刷新场景:一种是,用户主动触发的,,比如按钮点击;另一种是,应用程序自己调用的,,比如重新登录后、下拉刷新这些情况。 那这个机制是怎么运转的呢?它在架构上分三个角色——你可以理解为一个配合默契的小团队: - ,第一个角色:触发者,。任何一个组件都可以通过触发一个叫 `RefreshEvent` 的事件,来发出“我需要刷新”的信号。 - ,第二个角色:容器,。页面上会有一个“大总管”组件,它通过 `registerRefreshContainer` 来注册自己,专门接收刷新事件,然后统一协调整个刷新流程。 - ,第三个角色:参与者,。那些真正拿着数据、需要刷新的组件,会通过 `registerRefreshDeliverManager` 注册一个处理程序。当容器协调下来后,这些处理程序就去执行真正的数据刷新操作。 这样设计的好处是,刷新的逻辑是高度解耦的,不管你页面结构多复杂,都能很优雅地完成局部刷新。 另外,这个 API 是用来,替代过去 Aura 框架里的 force:refreshView, 的。如果你之前在 Aura 里用过,那现在转到 LWC,思想是类似的,但实现更现代。 还要注意一个很重要的点:,Lightning Data Service,也就是 LDS,天然支持 RefreshView API,。如果你用的是 `getRecord` 这类适配器,数据刷新它会自动帮你处理好。但是,如果你用的是自定义 Apex 方法,或者是 GraphQL 查询,那就必须自己动手了——在注册的刷新处理程序里面,要显式地去调用 `refreshApex` 或 `refreshGraphQL`,才能真正把数据拉回来。 最后,今天我们看的这一页只是一个开头。在这一章的后半部分,我们还会深入学习怎么通过,命名凭证从 Apex 调用外部 API,,以及一套完整的错误处理机制,覆盖 JavaScript、LDS 和 Apex 的各种错误。这样你写的组件才能既灵活又健壮。 那好,关于 RefreshView 的基本概念我们就先说到这儿。同学们可以稍微消化一下,想想自己项目里有哪些场景用得到它。有问题随时提,我们停下来聊一聊。

课程章节

本课程共有 6 个章节

  • 1

    RefreshView API — User Experience & Architecture

    第 318 页

    今天我们来聊聊RefreshView API,这个API能让你在Lightning Web组件里,灵活地刷新页面上的数据,而且不会把整个页面搞得天翻地覆。 你可以把RefreshView API想象成给页面局部洗澡,只冲洗需要的地方,而不是把整间屋子都浇一遍。它支持两种触发模式,一种是用户主动触发,比如你点了个按钮;另一种是应用程序自己触发,比如用户重新登录后,或者下拉刷新时。 先说用户触发的情况。你在组件里放一个刷新按钮,当用户点下去,按钮就会调度一个RefreshEvent事件。这个事件就像喊话:“喂,该刷新了!”离它最近的、注册了刷新处理的容器组件会抢先听到,然后启动一个“忙碌状态”的处理程序,屏幕上可能会显示一个旋转器,同时UI也准备好要刷新了。接着,这个容器里所有的后代组件都会收到信号,各自去拿最新的数据。等所有数据都同步完毕,刷新才算完成,旋转器消失,界面更新。 应用程序触发呢?就是代码里检测到某个条件,比如用户会话重新认证成功,或者你做了个下拉刷新手势,应用就自动启动同样的刷新流程。整个过程和用户触发一模一样,只是发起方变成了程序逻辑。 这里要提一个重要的概念: “视图”。在RefreshView API里,视图不是一个UI界面,而是所有订阅了刷新事件的组件的层级结构。这个API特别强大的一点是,你可以控制刷新的范围——不是整个页面都刷新,而是只刷新相关的部分。比如一个仪表板,你只刷新图表部分,不碰旁边的文本摘要。这就是所谓的“灵活范围控制”。 另外,Lightning Data Service,也就是LDS,它支持这个API,但它自己不会主动去拿新数据。也就是说,LDS帮你管理了数据缓存,但你得在组件里显式调用refreshApex()或者refreshGraphQL(),才能让LDS去服务器拉取最新数据。记住,是你在控制什么时候刷新,不是自动的。 这个API在Lightning Web Security(LWS)和Lightning收件箱里都能用,只不过注册刷新事件的格式稍有不同,用的时候查一下文档就行。最后要提醒一点:Wire服务的数据更新是发生在RefreshView API上下文之外的,也就是如果你用wire去获取数据,它本身不会自动融入这个刷新流程,你需要自己处理好它们的协作。 这样讲解下来,你应该能明白RefreshView API是如何帮我们高效、精准地管理数据刷新了。有什么问题,随时问。

    查看详情
  • 2

    Register Refresh Handler — Participant Components

    第 319 页

    好,咱们今天来讲讲这个刷新处理程序在Lightning Web Components里是怎么玩的,尤其是在LWS和Lightning收件箱这两种环境下有什么不一样。 你可能会问,什么叫刷新处理程序?简单说,就是当外部的数据变了,容器组件想让里头的组件自己重新拉数据、更新界面,这时候就会触发一个刷新动作。那组件得提前告诉容器:“嘿,我准备好了,你可以来刷新我。” 这个“告诉”的过程,就是在`linkedCallback()`生命周期里,调用一个叫`registerRefreshHandler`的方法来注册一个处理函数。注意,这里说的是`registerRefreshHandler`,你看到的Slide里写的`registerRefreshDeliverSector`应该是笔误,我们实际用的是`registerRefreshHandler`。 但麻烦的地方来了——LWS和Lightning收件箱的注册方式不一样。LWS是新一代的运行时,写法简洁:直接传`this`和处理函数引用就好。而老的Lightning收件箱环境,必须用`this.template.host`作为上下文,并且要把处理函数用`.bind(this)`绑定好,不然里头的`this`可能就指错了。所以你在写代码时,很可能得做一个判断,看当前是哪种模式,再用对应的写法。 那这个处理函数得长什么样呢?它必须返回一个Promise,这个Promise最终要解析成一个布尔值。如果是`true`,意思就是“我这边刷新好了,你可以继续去刷新我的子组件”;如果是`false`,就是“到我这打住,下面的别动了”。所以你可以用它来控制刷新的深度,比如你发现数据没变化,没必要让子组件再动,就可以返回`false`。 处理函数里面一般干什么呢?最常见的就是重新获取数据,顺便更新一下UI状态,比如转个圈圈、弹个提示,然后把组件内部状态重新跟数据源同步一下。所以它是个很重的操作,别随便到处写。 还有一点很重要:刷新是自上而下、宽度优先的。也就是说,容器先触发自己的刷新处理函数,等它Promise resolve了,如果是`true`,再去刷新直接子级;所有子级都处理完了,才会到孙子级。这保证父组件先准备好,子组件再动,逻辑不乱。 最后,别忘了一件事:当组件被移除时,你得在`disconnectedCallback()`里,用之前保存的处理程序ID,调用`unregisterRefreshHandler`来取消注册。不然它可能还留着个回调,内存泄漏或者异常调用就麻烦了。 要记住:每个组件只注册自己的处理程序,刷新后代是框架自动根据你返回的布尔值来决定的,你不用替后代操心。 所以整体看来,这就是一套让组件主动声明“我能刷新自己”,并且在合适的时机接收刷新的机制。LWS和收件箱的差异只是历史包袱,你写代码时注意适配一下就行。 好了,这个点就说到这儿,有什么问题随时问。

    查看详情
  • 3

    Signal Refresh & Register Container

    第 320 页

    同学们,今天我们来讲一下LWC刷新架构的三个关键角色,它们通过闪电/刷新模块连在一起工作。你可能会疑惑,一个简单的刷新操作,怎么还要分成几个部分?别急,我慢慢给你说。 首先,第一个角色是“事件触发者”。任何组件都可以发出一个名叫RefreshEvent的信号,告诉大家“嘿,该刷新啦!”通常,这是一个按钮组件,比如你点了一个“刷新数据”按钮。 第二个角色是“刷新容器”。容器需要主动注册,用registerRefreshContainer这个方法,来监听刷新事件。当容器收到事件后,它会收到一个叫freshPromise的承诺。这个承诺很贴心,它会等所有处理刷新的程序都完成后才解决,并且会返回一个状态,比如刷新完成、因为报错完成、或者警告。容器可以用这个状态来做很多事情,比如显示加载动画、处理错误、或者弹出提示。 第三个角色是“参与者”。各个组件注册自己的处理程序,来真正执行刷新数据的逻辑。容器在它的模板里,一定要包含处理程序的组件,还有触发事件的按钮组件。 这里有个重要的机制:刷新事件会像泡泡一样沿着DOM向上冒泡。也就是说,离触发按钮最近的、注册过容器的祖先组件,会先收到这个事件。另外提醒一下,LWS和RST环境下,注册参数的格式稍微有点不同,使用时留意一下就行了。 好了,这就是刷新架构的简单模型:按钮触发事件,容器统一管理状态,参与者干活。记住这个小分工,后面用起来就清楚多了。

    查看详情
  • 4

    Considerations & Call APIs from Apex

    第 321 页

    同学们,咱们今天聊聊两个听起来有点技术,但实际上很好理解的话题:一个是 RefreshView API 的使用注意事项,另一个是当你在 Apex 里调用外部 API 时,怎样才能安全又规范,也就是“命名凭据”的用法。 先看 RefreshView API。简单说,它就是帮你刷新组件视图的工具,但用的时候有几条规矩要记牢。 第一,什么时候用它?当你处理的数据不是直接来自 Lightning Data Service(LDS),而是来自 Aura 组件或者第三方来源的时候,你就需要手动刷新视图。因为 LDS 能自动感知数据变化,但 Aura 或外部数据不会自动通知你的 Lightning Web Component。 第二,不要偷懒把所有组件都注册上,要“仅注册需要参与的组件”。也就是说,只把那些真正需要收到刷新通知的组件加进去,避免不必要的性能开销。 第三,每个组件必须自己注册自己的回调函数。这点很关键——后代组件可不会自动跟着刷新,即使你的父组件注册了,子组件也得单独注册才能收到通知。 第四,容器组件也可以按类似的方式注册,这样就能建立起一棵可控的“刷新树”,让你能按范围刷新,而不是整个页面都动一遍。 好,接下来我们看 Apex 里调用外部 API 的安全姿势——“命名凭据”。 首先要知道,Salesforce 的安全策略很严格,默认情况下,就算是 Apex 也不能随便向任意的外部网站发请求。这是为了防止敏感数据泄露或被恶意利用。 那么想调外部接口怎么办?用“命名凭据”就是一种安全又受控的旁路方案。你可以把“命名凭据”理解成一个提前配置好的通行证,里面定义好了要访问的端点 URL 和身份验证参数(比如用户名密码或者 OAuth 令牌)。这样,你的代码就不用硬编码密码和地址,统一用这个命名凭据的名字去引用,既安全又方便管理。 另外,在做任何 Apex 调用之前,一定要记住这条原则:先从 JavaScript 端尝试使用 Lightning Data Service。因为 LDS 已经帮我们封装好了安全、缓存和刷新机制,能用它解决的,尽量用它。只有当 LDS 不支持你要操作的实体(因为 LDS 只支持 UI API 的一部分对象)时,才退而求其次,用带命名凭据的 Apex 类去调用外部接口。 最后,也是最要紧的提醒:对于所有用到命名凭据的代码,务必要仔细检查,确保不会因为配置不当或者参数拼接问题,造出安全漏洞,比如把内部凭证泄露出去。 总结一下,今天两个要点:RefreshView 要按需注册、各管各回调;调外部 API 首选命名凭据,代码里先试 LDS,不行再用 Apex,而且时刻盯紧安全。这样一来,你的组件刷新高效又稳定,外部调用也合规又安心。

    查看详情
  • 5

    Work with Errors — Types & Lifecycle

    第 322 页

    好,各位同学,今天咱们来聊一聊LWC里的错误处理。你在开发的时候,肯定碰到过代码里出毛病的情况,别慌,咱们把错误的类型和它们的脾气搞清楚了,就能稳稳地接住它们。 LWC里,错误大概来自三个地方。 第一种是,JavaScript原生错误,,就是你自己写的JS代码里出了岔子。比如你拼错了一个变量名,就会得到一个 `ReferenceError`;或者写了一句语法不通的话,就会得到一个 `SyntaxError`。这些错误都是用标准的 `throw` 语句抛出来的,咱们用 `try-catch` 包起来就能抓住。 第二种是,LDS错误,,也就是闪电数据服务(Lightning Data Service)出错。当你用 `@wire` 连接一个数据源,比如从一个记录里拿数据,如果网络抽风了,或者记录不存在,这个错误会悄悄地藏在 wire 返回对象的 `error` 属性里。所以记得去检查这个属性。 第三种是,Apex错误,,这是后端抛给我们的。比如你调用一个Apex方法,里面做了DML操作,但验证规则不通过,就会扔过来 `DmlException`;如果是安全权限问题,会有 `SecurityException`;或者开发人员自己定义的一些异常。它们都会在LWC可调用方法的返回值里以错误形式体现。 好,现在重点来了。这些错误发生之后,它们的“旅行路线”是完全不一样的,这取决于你写的是同步代码还是异步代码。 我来给你打个比方: - ,同步错误,就像在一条直直的走廊上泼了一盆水,水会顺着走廊一路向前流,流过每一个组件,最终流到最外层的应用程序那里。如果中间没人拿拖把吸掉它(也就是你不 `catch` 它),最后浏览器就会弹出一个很明显的错误提示框,里面还带着堆栈信息,用户一定能看见。所以同步代码里的错误,用户基本都能察觉到。 - ,异步错误,就完全不一样了。它更像你把一杯水偷偷倒进了地漏里,水直接流进了下水道,地面上一滴痕迹都没有。在代码里,异步操作——比如 Promise 里的 `then/catch` 没写全,或者 wire 服务的回调里出了问题——这些错误如果没有被显式地处理,它们不会爬上组件树,也不会触发那个用户可见的弹窗,而是直接默默地跑到了,浏览器控制台,里。用户正常用页面,可能根本不知道发生了错误。 这个区别非常关键。很多同学刚上手 LWC 的时候,觉得“哎,之前那个变量写错了就弹框了,怎么这次 wire 里的断句就没动静了呢”,就是因为后者是异步的。这也就意味着,对于所有异步代码,不管是 Promise 还是 wire 的回调,你,必须亲手处理错误,,要么显示一个友好提示,要么记个日志,总之不能指望它自己蹦出来给用户看。 举个例子,假设你有一段访问服务器端数据的逻辑,不小心把 `server.targets.Value` 拼错了。如果你在同步的 `connectedCallback` 里这么写,那个不可阻挡的弹出框会直接怼到用户脸上;可你要是把它放在一个 wire 处理函数或者一个 `fetch` 的 `.then` 里面,什么弹窗都不会有,只有你自己打开控制台才能看到那个刺眼的红叉。 所以记住今天的小口诀:,同步错误自动冒泡,用户一定看得到;异步错误悄悄溜走,你得主动把它捞。, 以后写 LWC 的异步操作时,别忘了给它加一个安全网——用 `.catch` 或者检查返回的 `error`,给用户一个体面的体验。 好了,这堂课就讲到这里,大家试着去自己的组件里排查一下,看看哪些地方可能漏掉了错误处理吧。

    查看详情
  • 6

    Display & Propagate Errors

    第 323 页

    各位同学,咱们今天聊一聊错误处理这个容易被忽略但又特别影响用户体验的话题。想象一下,用户在操作时遇到错误,突然看到一个风格怪异、措辞模糊的红色弹窗,是不是既困惑又恼火?所以,错误显示必须做到“一致且有帮助”——所有报错看起来都像一家人,而且告诉用户到底哪里错了,该怎么修。 Salesforce 给我们提供了很便捷的内置工具。第一个就是 ShowToastEvent,它能弹出一个标准的 toast 通知,像一个小提示条,你可以设置 title、message 和 variant。但真正的麻烦在于,后端报上来的错误长得五花八门——有时是 Apex 异常,有时是 LDS 的错误结构,有时干脆是 JavaScript 抛出的原始对象。怎么办呢?我们接下来讲一个神器,叫做 reduceErrors。 reduceErrors 来自 ldsUtils 模块,它专门负责把各种形状的错误“暴力”拆解,最后压平成一个纯字符串的数组。比如你尝试调一个 wired 方法失败了,直接用 reduceErrors(error) 就能得到一段人类能读懂的报错文本,你就可以安心地塞进 toast 的 message 里了。这里面有一个重要原则:,永远在消息里加上纠正措施,。比如“无法加载记录,请确认您有读取权限”而不是只报“Error 403”。让用户知道接下来该点哪里、找谁或者刷新页面。 如果你想搭建一个更复杂的界面,Salesforce 的 lwc-recipes 项目里提供了一个叫 errorPanel 的组件,它就是一个可以拿来即用的错误显示模板,上方图标加文案,样式统一又美观,你只需要传给它一个 errors 数组就行。这能节省你反复造轮子的时间。 接下来我们说错误传播,就像传球游戏,错误得按约定路线走,不能乱扔。我们有三种标准方法: 1. ,throw,:用于组件树上抛同步错误。子组件里出错,直接 throw new Error('…'),然后上层的 error boundary 或者 try-catch 就能接住。但注意,这只在同步代码里有效,异步回调里 throw 没用,要考虑定制事件。 2. ,CustomEvent,:典型的孩子向父母喊话。子组件用 this.dispatchEvent 发一个带错误信息的事件,父组件在模板里监听 onerror,然后统一处理。这样一来,错误处理和显示逻辑都集中在父组件里,容易维护。 3. ,Lightning Message Service 或 pubsub,:当你的错误需要跨越不同 DOM 分支,比如从工具条组件发给主面板,它们之间没有直接的父子关系,就用消息通道。LMS 是官方推荐,pubsub 更轻量。无论哪种,都相当于一个广播电台,谁想知道错误就去订阅。 最后说说最佳实践模式,可以总结成一句话:,错误从子组件来,在父组件集中处理,用统一的方式温柔地告诉用户,并且永远不会悄悄失败,。具体做的时候,要显式处理所有的同步错误和所谓“rewrite”错误——也就是把原始错误包装成用户看得懂、有行动指引的信息。比如用 reduceErrors 解析后,拼上“请刷新后重试”之类的话。这样整个应用的容错性、品牌感和友好度都会提升一大截。 好,这一页的核心就这些,大家记住:一致、有帮助、有行动指引,让错误不再可怕。

    查看详情