目录
- 引言
- 本节目标
- [先理清:快照 ≠ 数据源](#先理清:快照 ≠ 数据源)
- 步骤一:认识数据查询(Query)
-
- [1.1 Query 是什么](#1.1 Query 是什么)
- [1.2 能读到什么、能调什么](#1.2 能读到什么、能调什么)
- [1.3 触发方式只有两种](#1.3 触发方式只有两种)
- [步骤二:新建 query1](#步骤二:新建 query1)
-
- [2.1 创建](#2.1 创建)
- [2.2 配查询条件:只查当前选中的那个部门](#2.2 配查询条件:只查当前选中的那个部门)
- [步骤三:右侧部门名称改成绑 query1](#步骤三:右侧部门名称改成绑 query1)
- [步骤四:表单容器改成接收 query1 的数据](#步骤四:表单容器改成接收 query1 的数据)
-
- [4.1 详情用文本组件拼](#4.1 详情用文本组件拼)
- [步骤五:保存后补一句 trigger](#步骤五:保存后补一句 trigger)
-
- [5.1 saveDept 的收尾](#5.1 saveDept 的收尾)
- 串起来跑一遍
- 本节成果
- 下一篇预告
引言
上一篇,部门的增删改做完了,页面看上去"能用了"。
受制于组件的限制,存在如下几个问题:
- 在树上点一个部门,右侧正常;
- 把「交付中心」改名成「交付中心(华东)」保存 → 树上的名字变了,右侧顶部还写着旧名字;
- 新增一个子部门保存 → 树刷新了,右侧那块详情却没动静。
这一篇我们不动增删改的主流程,只做一件"架构级"的改造:给右侧详情换一个真正的数据源------数据查询(Query),然后在数据发生变化的时刻手动让它重查一次。
本节目标
今天完成 5 件事:
- 想清楚"旧数据"是怎么来的------快照 ≠ 数据源;
- 认识微搭的数据查询 Query:它是什么、能读到什么、怎么触发;
- 新建一个「内置数据表查询」
query1,用currentDeptId当查询条件; - 把右侧的部门名称 和表单容器 改成绑
query1的数据; - 在保存的收尾处补一句
await $w.query1.trigger(),让右侧跟着一起更新。
完成后,右侧详情永远是数据库里的现值,修改时能立刻反映出来。
先理清:快照 ≠ 数据源
先把旧方案的数据流摆出来,问题一目了然:
text
用户在树上点中「交付中心」
│
▼
onDeptSelect 拿节点的 label / value
│
├──▶ currentDeptName = '交付中心' ← 这一刻拍下的「快照」
│
└──▶ currentDeptId = 'd03'
│
├──▶ 文本组件显示 currentDeptName
└──▶ 表单容器按 _id = 'd03' 自动查一次
─────── 之后你把「交付中心」改名保存 ───────
数据库里的 name 变了
树重新加载,显示新名字 ✔
但 currentDeptName 还是 '交付中心' ✘ ← 快照不会自己更新
表单容器的 _id 还是 'd03'(没变) ✘ ← 依赖没变,它不会重查
两条链路各自"卡"在了同一个地方:它们的数据源是一次性的,不会跟着库里的数据变。
currentDeptName是点树那一刻拍下的快照,写进去之后就再没人改它;- 表单容器靠「
_id变化」来触发重查,而改名并不会让_id变------依赖没变,组件就不动。
把一个"会过期的东西"当数据源用,就一定会出现"显示旧数据"。这不是配置错了,是方案选错了。
那正确的做法是什么?让右侧去认一个"每次问都能拿到最新值"的东西 ------微搭里这个东西叫 Query(数据查询)。
步骤一:认识数据查询(Query)
1.1 Query 是什么
按官方定义(Query 数据查询介绍):
Query 是一个静态 JS 对象,主要作用于后端相关的数据获取和更新等操作......可以通过与变量类似的方式在组件配置的表达式中进行引用,例如
query1.data......具备与变量一致的生命周期以及作用域。
翻译成大白话:Query 就是"挂在页面上的一个查询" ,你配好"查哪张表、按什么条件查",它就替你把结果放在 query1.data 里;组件用 fx 绑 query1.data.xxx,就等于"直接盯着数据库"。
它和普通变量最本质的区别:
| 页面变量 | 数据查询 Query | |
|---|---|---|
| 值从哪来 | 你手动赋进去的(一次性的) | 每次问数据库拿回来的 |
| 会不会过期 | 会(你不改它就一直是老值) | 不会(trigger() 一下就重新查) |
| 适合放什么 | 选中的 id、弹窗标题、表单场景 | 要展示的明细数据 |
1.2 能读到什么、能调什么
Query 上有 5 个成员,本篇用得到 2 个:
| 成员 | 类型 | 说明 |
|---|---|---|
$w.query1.data |
Object | 查询成功后的数据,默认 null |
$w.query1.error |
Object | 查询失败时的错误对象 |
$w.query1.isFetching |
Boolean | 是否正在加载中 |
$w.query1.trigger() |
方法 | 在代码里手动触发这次查询 (可传参,如 trigger({ aaa: 10 })) |
$w.query1.reset() |
方法 | 把 data 和 error 重置为 null |
两种引用方式,记牢:
javascript
// ① 在组件的 fx 表达式里:直接读结果
$w.query1.data.name
// ② 在自定义方法里:手动触发一次查询
await $w.query1.trigger();
1.3 触发方式只有两种
新建 Query 时,编辑器右侧会让你选触发方式,官方给的就是这两个:
| 触发方式 | 什么时候执行 | 适合的场景 |
|---|---|---|
| 入参变化时自动执行 | 查询条件里用到的变量一变,自动重查 | 点树、切筛选条件这类"条件变了就要重新看"的读操作 |
| 手动触发更新 | 只有代码里调 trigger() 才执行 |
完全由代码控制的时机 |
本篇的选择是:选「入参变化时自动执行」,同时在保存成功后手动补一句 trigger()。
为什么两个都要?
- 选自动 :点树 →
currentDeptId变 → Query 自动重查 → 右侧联动,这部分体验和第 3 篇一模一样,不用改; - 补手动 :改名保存后,
currentDeptId并没有变 ,自动触发不会发生------所以只能自己喊一声trigger()。
步骤二:新建 query1
2.1 创建
在编辑器左下角代码区 ,点+ 打开新建面板。选择「新建内置数据表查询」

数据模型选「部门(ct_dept) 」,触发方式选择入参变化时自动执行,方法选择查询单条

详情信息里需要返回关联关系的字段,我们需要把上级部门的信息也返回

2.2 配查询条件:只查当前选中的那个部门
这是建立"数据源"的关键一步------把查询条件接到 currentDeptId 上。
在 Query 的查询条件里加一条:
| 字段 | 运算符 | 值 |
|---|---|---|
数据标识(_id) |
等于 | $w.page.dataset.state.currentDeptId |
「值」这一栏不要手输,点旁边的 fx 按钮,从变量里选 currentDeptId(和第 3 篇给表格配筛选是同一个套路)。

步骤三:右侧部门名称改成绑 query1
先把最简单的那处改掉------顶部那个显示部门名称的文本。
第 3 篇里它绑的是变量(快照):
javascript
// 旧:读的是点树那一刻的快照
$w.page.dataset.state.currentDeptName || '请选择部门'
现在改成读 Query 的结果(现值):
javascript
// 新:读的是"刚才查回来的那条数据"
$w.query1.data?.name || '请选择部门'
操作:选中该文本组件 → 「文本内容」→ 点 fx → 粘贴上面的表达式 → 保存。

改完之后你会发现:点树时它照样会变 (因为 currentDeptId 一变,Query 自动重查,data.name 跟着变),但两者的性质已经完全不同了------它不再是"记住的名字",而是"当前库里那条记录的名字"。
步骤四:表单容器改成接收 query1 的数据
这一处最关键,也最容易配错。先看清楚它现在是什么状态(第 3 篇配的):
| 属性 | 现在的值 |
|---|---|
表单场景 formType |
read(查看) |
数据模型 dataSourceName |
ct_dept |
| 数据标识(_id) | $w.page.dataset.state.currentDeptId |
问题就出在第三行:表单容器自己会按 _id 去查一次库 ,而 _id 不变它就不查------所以我们再怎么改库,它都无感。
4.1 详情用文本组件拼
我们使用网格布局来搭建详情页面,修改常用布局为6:6

在列里添加文本组件

给文本组件绑定文本内容,绑定表达式如下:
bash
"部门名称:"+($w.query1.data?.name||"")

其余字段按照如下表达式分别绑定到对应的文本内容里
javascript
"部门编码:"+($w.query1.data?.code||"")
"上级部门:" + ($w.query1.data?.parent_id?.name || "")
"排序:" + ($w.query1.data?.sort || "")
"状态:"+($w.app.utils.formatEnum($w.query1.data?.status, 'shifuqiyong', $w.app)||"")
关联字段(上级部门)查回来是个对象 ,所以取名字要多走一层
.name。取_id则是$w.query1.data?.parent_id?._id------这和前几篇"界面用字符串、入库用对象"是同一件事的两面。
步骤五:保存后补一句 trigger
现在到了本篇要解决的"正主":数据改了之后,让右侧也跟着改。
5.1 saveDept 的收尾
第 4 篇的 saveDept 在最后是这样收尾的(树 + 表格):
javascript
// 旧:只刷新了树和表格
await $w.page.handler.loadDeptTree({});
if ($w.table1?.refresh) {
await $w.table1.refresh();
}
现在多补一句,让右侧详情一起重查:
javascript
// 新:树、右侧详情、下级表格,一个都不能少
await $w.page.handler.loadDeptTree({});
// 关键新增:强制 query1 重新查一次
// 改名后 _id 没变,"入参变化自动执行"不会触发,只能手动喊一声
await $w.query1.trigger();
if ($w.table1?.refresh) {
await $w.table1.refresh();
}

串起来跑一遍
场景一:改名后右侧立刻同步
- 树上点「交付中心」→
currentDeptId = 'd03'→query1自动重查 → 右侧名称和表单显示d03的值; - 点「编辑」,把名称改成「交付中心(华东)」→ 保存;
wedaUpdateV2写库成功 → 收尾三连:loadDeptTree({})→ 树上的名字变成「交付中心(华东)」;$w.query1.trigger()→ 右侧名称同步变成「交付中心(华东)」(旧方案在这里会一直是「交付中心」);table1.refresh()→ 下级列表照常。
本节成果
今天我们做完了什么?
| 维度 | 成果 |
|---|---|
| 概念 | 分清快照变量 与数据源 Query:变量存"条件",Query 存"内容" |
| 新组件 | 用通了「内置数据表查询」:$w.query1.data / trigger() / 两种触发方式 |
| 刷新方案 | loadDeptTree 管树、query1.trigger() 管右侧、table1.refresh() 管列表,三处收尾各司其职 |
到这里,部门管理页的读链路才真正闭环:左侧是树,右侧是"当前这条记录的现值",改完立刻看得到。
下一篇预告
部门建完了,接下来就该往部门里放人了。
下一篇我们做「人员管理」,会碰到几个新问题:
- 人员要挂部门,部门是关联字段------怎么在表单里选一个"树形的"部门?(下拉树 / 级联选择)
- 人员列表要按部门筛选,还得支持"本部门及以下";
- 返回部门管理,把
removeDept里那段注释掉的「人员校验」正式打开(现在它一直因为"人员模型还没建"而睡着)。
从"组织结构"到"组织里的人",这是数据真正开始生长的下一步。