使用 Wire Service 获取数据 — LWC @wire 完全指南

全面掌握 LWC Wire Service。涵盖 @wire 语法与 @salesforce/schema 导入(对象/字段/关系字段/复合字段规则/导入限制)、$ 响应式前缀(动态配置三种属性/顶层限制)、装饰属性 vs 装饰函数(选择指南/初始默认值/data-error 生命周期)、Wire Service 数据生命周期(配置完整评估/异步性质/缓存行为/多次 emit/手动刷新禁用轮询)、getRecord 实战示例(lightning-formatted-* 显示/模板守卫/getFieldValue)、LDS 错误处理(异步陷阱/FetchResponse 结构/body 格式差异/四种 API 错误体/ldsUtils)、Wire 搭配基础组件(输入组件列表/显示组件列表/姓名表单+称谓/带地图地址显示)。...

📅 2026/7/19 ✍️ ponybai 🏷️ lwc, salesforce, data

使用 Wire Service 获取数据

Wire Service

LWC 使用响应式 wire service 读取 Salesforce 数据。在 JS 类中用 @wire 装饰器指定 Lightning Data Service(LDS)wire adapter——adapter 定义数据形状,wire service 以不可变流方式提供数据。优先使用返回最少数据的 adapter 以提升性能。先用 lightning-record*form 组件检查是否有更简单的方式。

Wire Service 语法与 @salesforce/schema 导入

语法与 Schema
import { adapterId } from 'adapterModule';
@wire(adapterId, adapterConfig) propertyOrFunction;

// 导入对象和字段引用(强烈推荐——编译时验证/防删除/级联重命名)
import ACCOUNT_OBJECT from "@salesforce/schema/Account";
import ACCOUNT_NAME_FIELD from "@salesforce/schema/Account.Name";
import OWNER_NAME from "@salesforce/schema/Account.Owner.Name";  // 最多3层关系字段

// 配置对象:$前缀 = 动态响应式属性
@wire(getRecord, { recordId: "$recordId", fields: [ACCOUNT_NAME_FIELD] }) record;

@salesforce/schema 导入优势:Salesforce 验证对象和字段存在、防止被删除、重命名时级联更新源码、确保变更集和包包含依赖。命名惯例:OBJECTNAME_OBJECTFIELDNAME_FIELD(指南非规则)。

复合字段规则:读取可用复合字段(如 Contact.Name);创建和更新必须用独立字段(Contact.FirstName + Contact.LastName)。地址和地理定位字段仅通过字符串语法访问独立字段。

导入限制:仅支持标准对象和自定义对象(__c)。Person Account __pc → 从 Contact 导入对应自定义字段。外部对象 __x → 通过 Apex SOQL 获取。Knowledge__kav → 用字符串语法 'Knowledge__kav.Title'

响应式 $ 前缀 —— 动态配置

$ 前缀

配置对象中值前加 $ 前缀 → 引用组件实例属性(this.propertyName)→ 响应式:属性值变化时 wire service 重新提供新数据,组件重渲染

@api recordId;
@wire(getRecord, { recordId: "$recordId", fields }) account;
// $recordId 动态响应式——recordId 变化时自动重新获取
// fields 是静态值——不变化

// 支持三种动态属性:私有属性、getter-setter 属性、@api 属性
// $ 只能用于顶层值——嵌套在数组中如 ['$ids'] 变成字面字符串!

不带 $ 的值是静态的——不随组件状态变化。可以用一个 @wire 输出作为另一个 @wire 输入——如 $record.data.fieldName

装饰属性 vs 装饰函数

属性 vs 函数

装饰属性(消费数据原样):结果返回到属性的 data/error 子属性。初始默认值 { data: undefined, error: undefined }。数据可用时设 data(error=undefined)→ 新版本数据到达时更新 data。错误时设 error(data=undefined)。

@wire(getRecord, { recordId: "$recordId", fields: [NAME] }) record;
// record.data → 数据可用时填充 | record.error → 错误时填充
// 模板中用 lwc:if={record.data} 检查

装饰函数(需要处理逻辑):每次新数据提供或错误发生时调用。参数对象含 dataerror(顺序无关——因为是解构对象)。调用时机可能在连接或渲染之前或之后。

@wire(getRecord, { recordId: "$recordId", fields })
wiredAccount({ data, error }) {
  if (data) { this.record = data; this.error = undefined; }
  else if (error) { this.error = error; this.record = undefined; }
}

选择指南:属性——简单消费数据;函数——需要转换、错误处理、或派生状态的逻辑。

Wire Service 数据生命周期

数据生命周期

Wire adapter 仅在配置完整时(所有动态参数有值)才被评估——如果参数依赖父组件 wire 结果,可能需要等待。

生命周期顺序:constructor() → 配置完整 → 默认值 provision({data:undefined, error:undefined})→ connectedCallback() → render() → renderedCallback() → 数据到达(data 填充)→ render() + renderedCallback() 再次触发。

关键原则:

  • LDS wire 可以在配置不变的情况下多次 emit 数据——LDS 控制这些 emit,与 LWC 生命周期无关
  • Wire adapter 调用是异步的(除非数据已缓存)——响应和 Promise 解析顺序不保证
  • 不要在特定生命周期点依赖数据到达——wire 可以在任何时候接收数据
  • 数据在 LDS 缓存中已存在时无网络调用直接返回
  • Apex trigger 或 auto-launched flow 异步变更记录 → wire adapter 不会重新评估
  • 手动刷新:Apex wire → refreshApex();GraphQL wire → refreshGraphQL()不要用 setTimeout/setInterval 轮询——造成不必要服务器负载

获取记录数据 —— 实战示例

获取记录数据

完整示例——从 Contact 记录获取 Name/Title/Phone/Email 并用 lightning-formatted-* 组件显示:

// JS
import { getRecord } from "lightning/uiRecordApi";
const FIELDS = ["Contact.Name", "Contact.Title", "Contact.Phone", "Contact.Email"];

@api recordId;  // 记录页面自动提供
@wire(getRecord, { recordId: "$recordId", fields: FIELDS }) contact;

get name() { return this.contact.data.fields.Name.value; }
get phone() { return this.contact.data.fields.Phone.value; }

// HTML —— lwc:if 守卫防止 data 为 undefined 时报错
<template lwc:if={contact.data}>
  <p>{name}</p>
  <lightning-formatted-phone value={phone}></>
</template>
<template lwc:if={contact.error}>
  <c-error-panel errors={contact.error}></>
</template>

返回数据结构与 UI API 的 Record 响应 相同。推荐用 getFieldValue(record, field) 简化数据访问——替代 this.contact.data.fields.Name.value

处理 Lightning Data Service 错误

处理错误

LDS wire adapter 在资源不可访问时返回错误——无效 ID、缺失字段、记录被删除/共享变更、缓存中无数据且服务器离线。

异步代码错误处理陷阱:try-catch 只能捕获同步代码中的异常——setTimeout 回调中的错误在 try-catch 外部。必须在回调函数内部使用 try-catch。

Wire 函数中的错误处理模式:

@wire(getRecord, { recordId: "$recordId", fields })
wiredRecord({ error, data }) {
  if (data) {
    try { /* 处理结果 */ } catch(e) { /* 处理结果时出错 */ }
  } else if (error) {
    // 值供应时出错
    this.error = Array.isArray(error.body)
      ? error.body.map(e => e.message).join(', ')
      : error.body.message;
    this.record = undefined;
  }
}

错误响应结构:{ status, body:{message,statusCode,errorCode}, ok:false, statusText, errorType:"fetchResponse" }。Body 格式取决于 API:UI API 读 → 数组;UI API 写 → 对象(含对象级和字段级错误);Apex → 对象;网络错误 → 对象。Wire 首次触发前 data 和 error 都是 undefined——这不是错误状态,只是尚未触发。参考 lwc-recipes ldsUtils 工具函数。

Wire Service 搭配基础组件

搭配基础组件

lightning-record*form 不够灵活时,使用 wire service + 基础组件构建自定义 UI。

输入组件:lightning-input(通用输入)、lightning-combobox(下拉选择)、lightning-input-name(姓名复合字段)、lightning-input-address(地址)、lightning-textarea(多行文本)、lightning-radio-group/lightning-checkbox-group(选择组)。

显示组件:lightning-formatted-name/address/phone/email/number/date-time/text/url/rich-text/time——根据字段类型选择对应的格式化显示组件。

实战——自定义表单(姓名 + 称谓):getRecord 获取 FirstName/LastName/Salutation 字段值;getPicklistValues 获取称谓选项列表(需 recordTypeId + fieldApiName);lightning-input-name 绑定三个属性 + options 数组。

实战——带地图的地址显示:getRecord 获取 MailingStreet/City/State/Country/PostalCode;lightning-formatted-address 绑定各字段 + show-static-map 属性——点击地址或地图在新标签打开 Google Maps。

感谢阅读本指南。如需继续学习,请参阅下一章:跨 LWC 组件管理状态。