DEX475

Display Record Data in a Table

课程介绍

同学们,我们来看这张幻灯片,它介绍了 Lightning 数据展示相关的两个核心组件:,lightning-datatable, 和 ,lightning-tree-grid,。 首先,lightning-datatable 是一个标准的表格组件,它基于 Salesforce Lightning 设计系统(也就是 SLDS)的蓝图来展示行和列,外观和交互都非常统一。而 lightning-tree-grid 顾名思义,是在表格基础上扩展出树形结构,它可以展示带有父子关系、可以展开和折叠的分层数据,就像你在文件夹里一层层打开那样。 这两个组件有不少共同点:都支持自定义数据类型,也就是说你可以自己定义某一列怎么显示数据;都支持在表头或行上添加操作按钮;都可以让用户拖动调整列宽;都支持行选择并显示行号。这些是它们基础的能力。 当然,它们也有各自的特色。lightning-datatable 额外支持,列排序,、,内联编辑,(直接在单元格里修改数据)以及,无限滚动,(滚动到底部自动加载更多数据)。而 lightning-tree-grid 的独特之处就是那套可扩展的子行,让数据带有层次结构。 有一点需要特别注意:,这两个组件目前都不支持移动设备,,也就是说在手机浏览器或者 Salesforce 移动 App 里,你可能需要换用其他方案来展示数据。 本章内容会完整覆盖从最基础的表单显示开始,一路深入到自定义数据类型、内联编辑、可访问性(无障碍设计)以及性能优化,带领大家走过整个生命周期。 最后,关于怎么创建自定义数据类型,我们有两种方式:一种是直接继承 ,LightningDatatable, 或 ,LightningTreeGrid, 类,用代码扩展它们;另一种是利用插槽(slot)来动态传递自定义的渲染内容,这样加载起来更灵活。 好,这个幻灯片的核心就这么多。大家先有一个整体印象,后面我们逐一深入。

课程章节

本课程共有 9 个章节

  • 1

    Compare Datatable & Tree-Grid + Hierarchical Tables

    第 282 页

    同学们,今天我们来聊聊 Lightning Web Components 里面两个重要的展示组件:datatable 和树网格,也就是 tree grid。其实它们就像是表格的不同形态,各有各的擅长场景。 先说 datatable,它的强项在于很有交互感——支持排序、内联编辑,还有无限滚动,处理大量数据时用户不用翻页,一直往下滑就能加载更多。而树网格呢,它是专门用来展示有层级关系的数据的,比如带父记录和子记录的情况,每一行都可以展开,看到下一层的子数据,层次很清晰。 虽然场景不同,但它们也有一些共同的功能:都支持自定义数据类型,你可以自定义每一列显示成什么样子;都支持行操作,比如点击按钮触发动作;都能让用户调整列宽、勾选行,还可以显示行号。不过要注意一下,这两个组件目前都还不支持移动端的交互,所以在手机上使用时体验有限,这是它们共有的小遗憾。 那重点来了,如果想用树网格展示分层数据,该怎么处理数据呢?关键就在每一行的数据里加一个 `_children` 键。在 Apex 控制器那边,你可以用 SOQL 的子查询直接拿到当前记录的所有子记录;在 JavaScript 里,拿到数据后,要把这些子记录映射到父记录的 `_children` 字段里。这样树网格就能自动识别谁是父、谁是子了,一层层展开。 说到行操作,比如在行上放一个“编辑”按钮,点击后可以导航到这条记录的详情页面。这时候我们可以借助 `NavigationMixin` 来实现跳转,代码写起来也很简单。 最后记住,树网格这个组件本身需要接收几个重要属性:`columns` 定义列,`data` 传入处理好的数据,`key-field` 告诉组件每行唯一的标识字段,还有 `onrowaction` 用来监听行操作事件。把这几样东西配好,一个带层级展开的表格就出来了。 好了,关于 datatable 和树网格的功能对比,以及分层数据的处理方式,我们就先讲到这里。大家可以在练习中试着把父子关系数据拼成 `_children` 的结构,感受一下树网格的妙用。

    查看详情
  • 2

    Inline Editing — Basic Implementation with updateRecord

    第 283 页

    咱们今天讲讲在Lightning Web Components里给数据表做内联编辑,这功能其实就靠三个核心点:第一,列的 editable 属性得设为 true;第二,数据表上要通过 draft-values 绑定一个变量;第三,必须实现 onSave 处理器,用来响应保存动作。 当用户直接在单元格里修改内容时,组件会自动把这些变更收集到 draftValues 里。它是一个对象数组,每一项的键是记录 ID,值就是被改过的字段和新的数据。 那在 onSave 里我们要做什么呢?最常用的“收件箱保存模式”是这样的:先从事件参数中取出 draftValues,接着把每一条变更转换成 updateRecord 适配器需要的 { fields } 格式。然后很重要的一步,把 draftValues 清空,这样保存和取消的页脚就会自动隐藏。再用 Promise.all 一次性并行调用所有 updateRecord,因为每条记录的更新是独立的事务。成功之后弹个 toast 提示用户,并且用 refreshApex 刷新一下表格数据,让界面立刻反映最新值。 需要留意的是,每个 updateRecord 调用都是单独提交的,不会打包成一个事务。如果你希望多条记录在同一个事务里一起更新,就不能靠这种客户端方式了。正确的做法是:把已编辑的字段收集起来,调一个自己写的 Apex 控制器,在服务器端完成整体的 DML 操作,完成后在前端调用 notifyRecordUpdateAvailable(),把改动通知给 Lightning Data Service,这样 LDS 缓存就会被自动刷新,界面也同步过来。 记住啦,内联编辑就是这三件套,再加上 save 逻辑里选对策略——单条独立就用 updateRecord 和 Promise.all,需要打包事务就交给 Apex 统一处理。上手试一下就会很清楚。

    查看详情
  • 3

    Inline Editing — Bulk Update with Apex

    第 284 页

    同学们,今天我们来看一个非常实用的技巧:在 Lightning Web Components 里面,怎样一次更新多条记录,并且确保它们像绑在一起一样,要么全成功,要么全失败。这在处理像订单和订单行项目这种必须保持数据一致性的场景时,特别重要。 想象一下,你的页面上有一个数据表格,用户可能同时修改了好几行,然后点了一个“保存”按钮。如果你用一条一条单独更新的方式,比如多次调用 `updateRecord`,它们都是各自独立的事务。一旦中间某条因为验证规则失败了,前面已经成功保存的记录可不会自动退回去,数据就不一致了。 那更好的做法是什么呢?我们可以把这些要保存的变动,也就是 `draftValues`,一次性打包发给一个 Apex 方法。这个 Apex 方法收到的是一个 JSON 字符串,它会把它反序列化,还原成 sObject 的列表,然后执行一个单独的 DML 更新语句。因为是一个 DML 语句,Salesforce 会自动把它当作一个整体的事务。如果里面任何一条记录触发了验证错误,整个操作就会回滚,之前所有的更改都不会被保存。这就叫事务完整性。 在前端 JavaScript 这边,Apex 方法调用成功后,我们不能只是简单刷新数据。因为 Lightning Data Service,也就是 LDS,自己维护了一套缓存。我们需要告诉它:“嘿,你看一下这些记录,我已经在后台更新过了,你缓存的旧数据要清掉。” 怎么做呢?我们先调用 `notifyRecordUpdateAvailable`,把更新过的每条记录的 ID 传过去,LDS 就会标记这些记录需要重新从服务器获取。然后,如果我们页面上用的是 `wire` 来获取数据,还得再调用一次 `refreshApex`,把有线数据重新加载一下,这样表格里的信息才会是最新的。 总结一下,这种批量更新的 Apex 方法,相比一条一条独立更新,多了打包 JSON、调用 Apex、再通知缓存和刷新数据的步骤,但换来了一个核心保障:无论你有两条还是二十条相关记录要一起改,只要有一处不通过,全都恢复到未改之前的状态。这能帮你避免很多数据错乱的问题。 好了,今天的知识点就讲到这里,大家可以在课后试着在组件里实现一下,体会事务完整性的好处。

    查看详情
  • 4

    Custom Data Types — Extending LightningDatatable

    第 285 页

    同学们,咱们今天聊一个实战中非常有用的话题——如何自定义 Lightning Datatable 的单元格外观。默认表格只能展示文本、数字这类基础格式,但业务里咱们总想放个进度条、头像,或者可点击的按钮对吧?这就用到“自定义数据类型”。 简单说,就是定义一个静态的 `customTypes` 对象来告诉表格:遇到某种类型时,用我给你的模板来渲染。这个对象挂在扩展自 `LightningDatatable` 的组件上。每个自定义类型要指定三个东西: 1. ,模板,:一个导入的 HTML 文件,决定了单元格长什么样。 2. ,typeLCS 数组,(Lightning Component Style?其实可以理解为模板里能访问的自定义属性名列表):比如你传了个 `highlightColor`,模板里就能用 `typeLCS.highlightColor` 拿到。 3. ,标准单元格布局,:是个布尔值,选 `true` 就用系统自带的内边距、对齐和可访问性支持,省事又合规;选 `false` 就是裸布局,完全自己控制。 模板里,你可以直接写简单的 HTML 标签,也可以在里面嵌入子组件(嗯,没错,把其他组件拖进来用)。那怎么跟数据联动呢?单元格的值用 `{value}` 就能取到,那些自定义属性就用 `{typeLCS.属性名}` 访问。 接下来是使用方式。我们需要做一个包装器组件,让它继承 `LightningDatatable`,并在里面通过 `@wire` 或者直接定义列时,用 `type: '自定义类型名'` 来引用。提到列,你还能基于 `fieldName` 做类映射,有条件地加上 CSS 类,控制样式。比如某个字段值大于阈值时标红。 总结一下:想扩展表格能力,就写一个自定义类型对象,配上模板和属性列表,继承基类组件,然后在列定义里指定类型,模板会自动接收数据和额外属性。是不是感觉一下子灵活多了?大家先理解这个原理,下一节我们动手写一个带状态指示灯的表格练练手。

    查看详情
  • 5

    Custom Data Types — Dynamic via Slots

    第 286 页

    好,我们来看一个很实用的知识点:在Lightning Datatable里,怎么用“基于插槽的方法”来加载自定义数据类型。这个方法最大的好处是动态加载,不用去扩展LightningDatatable这个基类。 你想象一下,你的表格里有一些特殊的列,比如显示星级评分、进度条或者复杂的组件。以前你得写很重的继承代码,但现在我们可以用一个“数据提供程序”组件,它就像一个工具箱,专门告诉你“我支持哪些自定义类型”。 这个数据提供程序组件内部有一个用`@api`装饰的`getDataTypes()`方法,它返回的就是自定义类型的定义,比如这个类型叫什么名字、对应的模板是什么、编辑时用什么组件等等。然后在父组件里,你用`lightning-datatable`的`customdatatypes`插槽,把这个提供程序传进去。 这里的关键是动态性:你可以在运行时决定加载哪些自定义类型。一个常见模式是这样的:一开始在构造函数里过滤出数据里用到的自定义列类型,然后通过一个`lwc:if`指令来控制提供程序是否显示,并且用一个数组来存放这些列定义,最后通过一个按钮点击才把它们展开添加到表格里。这样表格本身会监听插槽的变化,发现有新的自定义类型进来了,就自动更新列配置,用户体验很流畅。 使用的时候要注意几点:首先,如果你有扩展的类,一定要在`linkedCallback`里调用`super.linkedCallback()`,保证生命周期正常。其次,对自定义类型要显式地传入字段名来做排序,不要依赖隐式绑定。还有一条很重要的:千万别在自定义单元格内部嵌套数据对象,也就是说,传给单元格的原始数据要保持扁平,不要“包饺子”一样把一整个对象塞进去,否则性能和数据更新都会出问题。 简单理解就是:你需要特殊列,就写个提供程序,放在插槽里,然后告诉表格什么时候启用它,表格就会自己更新。这样既轻量又灵活,还不用改底层代码。

    查看详情
  • 6

    Custom Data Type Layout, Styles & Events

    第 287 页

    同学们,今天我们来聊一聊 Lightning Web Components 里数据表的自定义数据类型布局,这部分内容其实挺实用的,掌握了以后你能更灵活地控制表格里每个单元格的呈现样式。 首先,自定义数据类型的布局有两种选择:标准模式和裸模式。标准模式会匹配 Salesforce 的内置类型,还会自动加上辅助功能支持,让键盘导航、屏幕阅读这些都顺畅;裸模式呢,就非常纯粹,只提供最基础的结构,几乎不干涉你,方便你完全按照自己的设计来定制样式。简单说,标准就是“开箱即用”,裸就是“给你张白纸”。 接下来是列样式。你可以给整列的所有行应用一个静态的 CSS 类,直接用字符串就好;也可以根据不同行的数据动态切换样式,这时候就要用到基于 fieldName 的类映射了。不过要记住,动态样式只支持 SLDS 设计系统的实用类,不能直接用你自定义的 CSS 类,否则会出问题。所以想加自定义外观,还是在裸模式下通过内联样式或自定义模板实现更安全。 然后是内容对齐,用 cellAlignment 属性就能搞定,它支持 left、center、right 这三个值,分别对应左对齐、居中、右对齐,一眼就能看懂。 文本处理方面,有个 wrapText 开关,可以控制表格里的文字是自动换行还是截断。如果你想自己写自定义类型的模板,那换行模式要用 slds-wrapped 这个 SLDS 类,截断模式就用 slds-truncate,这样样式才符合规范。另外还有个 wrap-text-max-lines 属性,它能开启行数限制,让长文本只显示几行,后面自动加省略号,很适合用来做摘要展示。 最后讲讲事件。如果你在自定义数据类型模板里触发了一个自定义事件,想让这个事件穿透数据表内部、被外部的父组件监听到,那么就一定要给事件加上 composed: true 和 bubble: true,缺一个都不行。但有一种特殊情况:只要你的自定义类型是基于插槽的,那么事件可以直接在 lightning-datatable 元素上监听,不用额外操心传播的配置。记住这个差别,以后排查事件触发失败会很有帮助。 好了,这部分内容就是这些,理解了布局、样式、对齐、文本处理和事件传播这几个点,你就能玩转数据表的自定义列了。我们下次再见!

    查看详情
  • 7

    Make a Custom Data Type Editable

    第 288 页

    同学们,今天我们来看看,在 Lightning Web Components 的 datatable 里,怎么让自定义的单元格类型变得可以编辑。自定义类型默认只能展示,要让它像标准字段那样能双击编辑,需要三个紧密配合的步骤,我们一个一个来说。 第一步,你得创建一个独立的编辑模板,也就是一个专门的 HTML 文件,用于编辑状态下的单元格。这个模板里必须用 lightning-input 组件,而且它的 type 属性要跟展示模板里用来显示值的数据类型保持一致,比如文本、数字、日期等等。编辑模板会收到几个特殊属性,用来帮它正确显示:editedValue 是当前单元格的值,columnLabel 是列的标题文字,required 是一个布尔值,表示这一列在定义的时候有没有被标为必填,还有一个 typeLCS 是你在自定义类型上可以用的额外属性。为了键盘导航能正常访问到这个输入框,你需要在输入元素上加上 data-inputable="true" 这个属性。很简单吧,就是给 lightning-input 加一个 data-inputable='true'。 第二步,我们要把这个编辑模板引用到自定义类型的定义里。在你定义自定义数据类型的 JavaScript 文件里,导入刚才的编辑模板,然后在类型定义的对象里,把 editTemplate 属性指向它,同时一定要设置 standardCellLayout: true,这是键盘导航正常工作所必需的。 第三步,回到列的定义。在你想让它可编辑的列上,直接把 editable 属性设置为 true,这样该列用到自定义类型的地方,就会用我们刚配置的编辑模板去渲染编辑状态了。 完成这三步,自定义单元格就支持双击编辑了。接下来说说验证。基本的数据约束,比如数值范围、必填检查,lightning-input 自己就能处理。如果要做更复杂的验证逻辑,比如多个字段交叉校验,那需要在编辑模板对应的子组件里,向外暴露 validity() 函数来返回校验状态,同时暴露 showHelpMessageIfInvalid() 来显示报错提示。目前还不支持服务器端的验证规则,所以所有校验都要在前端完成。 最后提醒一个很重要的限制:编辑模板里只能放单个基础的输入组件,你要用 lightning-input,千万不要使用 lightning-input-field,而且不能嵌套组合多个输入组件,它只接受单一 input。这一点在实现的时候一定要记住。 好了,掌握这三个核心步骤和验证方式,你就能让任何自定义数据类型在 datatable 里顺滑地可编辑了。大家可以动手试试看。

    查看详情
  • 8

    Datatable Accessibility — Navigation & Action Modes

    第 289 页

    好,我们来聊聊 Lightning Web Components 里数据表格的可访问性,特别是键盘交互,这部分非常重要,能让咱们的组件对所有人都友好。 首先,表格提供了两种键盘交互模式,就像两个不同的频道,让用户能用键盘高效操作。 第一种叫,导航模式,。你可以把它想象成在表格的各个单元格之间快速浏览。怎么进入呢?用户按下 Tab 键,焦点就进到表格里了。进来之后,用键盘上的箭头键,上、下、左、右,就能在单元格之间移动。这里要注意,表格里那些可以操作的元素,比如按钮、链接,在这个模式下默认不会被 Tab 键直接选中,它们的 tabindex 被设成了 -1,也就是跳过去了。但如果一个单元格里只有一个可操作的东西,那用户按 Enter 键就会直接激活它,省得再切模式,很贴心。 第二种叫,动作模式,。当你需要跟单元格里的具体元素交互时,比如点按钮、选下拉框,就要进入这个模式。怎么进去呢?也是通过按 Enter 键,或者直接按 F2 键(有些屏幕阅读器用户常用)。进去之后,在这个单元格内部,Tab 键和箭头键就可以在按钮、链接这些控件之间来回移动了,这些元素的 tabindex 被动态设成了 0,所以能被焦点访问到。这样用户就能用键盘操作单元格里的每一个小部件。 那有些同学可能会问,我自定义了一个数据类型,在单元格里放了几个按钮或者输入框,怎么让它也支持这种动作模式呢?很简单,你需要做两件事。 第一,在你的自定义组件模板里,每一个可以获取焦点的元素上,要绑上一个属性叫 `tabindex`,值等于一个叫 `internalTabIndex` 的变量。这个变量是由数据表格自动提供给我们的。同时,在这个元素自己或者它的外层容器上,加上一个属性 `data-navigation='enable'`,这就像是告诉表格:“嘿,这个单元格里有多项可以操作,请开启动作模式。” 第二,如果你这个自定义类型是通过子组件实现的,那情况稍微复杂一点,因为 `internalTabIndex` 需要从父组件传给它。在父组件里,属性名要写成 `internal-tab-index`,注意是连字符写法,绑定上值 `{internalTabIndex}`。然后在你子组件的 JavaScript 里,用 `@api` 装饰器暴露一个公开属性也叫 `internalTabIndex`,注意这里是驼峰命名。最后,在子组件的模板里,同样给可聚焦的元素设置 `tabindex={internalTabIndex}`,再加上 `data-navigation='enable'` 就行了。 总结一下,加这两个小属性,你的自定义单元格就能完美融入键盘操作模式,既符合无障碍标准,又提升了所有用户的操作效率。

    查看详情
  • 9

    Performance, Display Density & Usage Considerations

    第 290 页

    同学们,今天咱们要聊的这块内容,虽然看起来信息挺碎,但每一条都是在实际开发中能帮你少走弯路的宝贝。我先从性能优化说起,再到表单显示密度,最后落到记录类型和操作覆盖,咱们一步一步来理解。 好,先说,性能优化,。在Lightning里,有一条铁律——,数据集一定要小,。记住一个黄金上限:页面最多展示,1000行,,每行最多,5列,。超过这个数,用户体感就会明显变慢。别想着把所有数据一股脑全扔给浏览器,要用,无限滚动,去渐进式加载,用户滚到哪数据才跟到哪。还有,,内联编辑,一定要省着用,只把那些真正需要频繁改动的关键字段放开,其他字段就老老实实只读。自定义数据类型也往简单了做:尽量减少与服务端的往返交互,我们管这叫“Inbox操作”——也就是后台Apex的调用次数,要能省则省。对象关系嵌套不要太深,查询时用,LIMIT,来翻页,另外如果你已经加载了超过250行数据,列数最好控制在,20列以内,,这样界面的渲染压力会小很多。 聊完性能,咱们看一个常常被忽视但直接影响用户手感的功能——,显示密度,。在Lightning里,表格和表单标签的定位会跟着密度设置变。,舒适模式,下,标签稳稳地放在字段上方,看着清爽;而,紧凑模式,下,标签会和字段嵌在同一行里,节省空间。在记录表单组件`lightning-record-form`上,直接有个`density`属性,你可以把它设为`comfy`或者`compact`,这个设置会覆盖掉组织级的密度配置,非常适合按场景微调。如果想更细地控制某个字段的标签样式,还可以用单个字段组件的`variant`属性,比如`label-hidden`隐藏标签、`label-stacked`让标签搁在字段上面。另外,有一个CSS类值得记住:`slds-form-element_1-col`,把它加到表单元素上,能在紧凑模式下极好地拉近标签和字段之间的间距,让表单看起来更紧凑又不凌乱。 接下来,咱们谈,记录类型,。当你的对象有很多种记录类型时,应该先调用,`getObjectInfo`,这个服务,从返回的元数据里读出当前用户能用的记录类型有哪些,然后把选中的记录类型ID通过`record-type-id`属性传给`lightning-record-form`或者`lightning-record-edit-form`。这样表单就会自动按类型显示出对应的字段,不用你手动拼布局。 表单提交成功后,父组件怎么知道创建了哪条新记录呢?这就要靠,自定义事件,。监听表单的`onsuccess`事件,在回传的`event.detail`里能得到新记录ID,父组件拿到ID后就能做后续跳转或刷新列表了。这个模式让组件之间保持松耦合,一个表单不直接操作父级逻辑,只负责上报结果。 最后这个知识点虽然偏底层,但很多新人容易卡住——,标准操作覆盖,。假如你想把一个LWC做成新建、编辑这种标准动作的替代页面,直接引LWC是不行的。Lightning要求你必须把这个LWC,包裹在一个Aura组件里,,然后在Aura组件上实现`lightning:actionOverride`接口。简单说就是Aura做壳,LWC当内核,这样标准操作按钮点开时,系统才能正确识别并调用你的自定义界面。 好了,今天这几块内容杂而不乱,帮你梳理完它们之间的逻辑,下次写代码的时候试试带着这些优化和配置思路,整个应用体验立马就上来了。如果有哪个点没听明白,随时提,我再细讲。

    查看详情