@creatoria/miniapp-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +469 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +73 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +118 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +50 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/core/element-ref.d.ts +44 -0
- package/dist/core/element-ref.d.ts.map +1 -0
- package/dist/core/element-ref.js +213 -0
- package/dist/core/element-ref.js.map +1 -0
- package/dist/core/logger.d.ts +55 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +378 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/output.d.ts +21 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +56 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/report-generator.d.ts +24 -0
- package/dist/core/report-generator.d.ts.map +1 -0
- package/dist/core/report-generator.js +212 -0
- package/dist/core/report-generator.js.map +1 -0
- package/dist/core/session.d.ts +83 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +306 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/timeout.d.ts +49 -0
- package/dist/core/timeout.d.ts.map +1 -0
- package/dist/core/timeout.js +67 -0
- package/dist/core/timeout.js.map +1 -0
- package/dist/core/tool-logger.d.ts +83 -0
- package/dist/core/tool-logger.d.ts.map +1 -0
- package/dist/core/tool-logger.js +453 -0
- package/dist/core/tool-logger.js.map +1 -0
- package/dist/core/validation.d.ts +39 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +93 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +85 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/assert.d.ts +108 -0
- package/dist/tools/assert.d.ts.map +1 -0
- package/dist/tools/assert.js +291 -0
- package/dist/tools/assert.js.map +1 -0
- package/dist/tools/automator.d.ts +45 -0
- package/dist/tools/automator.d.ts.map +1 -0
- package/dist/tools/automator.js +186 -0
- package/dist/tools/automator.js.map +1 -0
- package/dist/tools/element.d.ts +253 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +615 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/index.d.ts +97 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1565 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/miniprogram.d.ts +79 -0
- package/dist/tools/miniprogram.d.ts.map +1 -0
- package/dist/tools/miniprogram.js +245 -0
- package/dist/tools/miniprogram.js.map +1 -0
- package/dist/tools/network.d.ts +65 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +205 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/page.d.ts +108 -0
- package/dist/tools/page.d.ts.map +1 -0
- package/dist/tools/page.js +307 -0
- package/dist/tools/page.js.map +1 -0
- package/dist/tools/record.d.ts +86 -0
- package/dist/tools/record.d.ts.map +1 -0
- package/dist/tools/record.js +316 -0
- package/dist/tools/record.js.map +1 -0
- package/dist/tools/snapshot.d.ts +82 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/snapshot.js +258 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/SIMPLE_USAGE.md +210 -0
- package/docs/api/README.md +244 -0
- package/docs/api/assert.md +1015 -0
- package/docs/api/automator.md +345 -0
- package/docs/api/element.md +1454 -0
- package/docs/api/miniprogram.md +558 -0
- package/docs/api/network.md +883 -0
- package/docs/api/page.md +909 -0
- package/docs/api/record.md +963 -0
- package/docs/api/snapshot.md +792 -0
- package/docs/architecture.E-Docs.md +1359 -0
- package/docs/architecture.F1.md +720 -0
- package/docs/architecture.F2.md +871 -0
- package/docs/architecture.F3.md +905 -0
- package/docs/architecture.md +90 -0
- package/docs/charter.A1.align.yaml +170 -0
- package/docs/charter.A2.align.yaml +199 -0
- package/docs/charter.A3.align.yaml +242 -0
- package/docs/charter.A4.align.yaml +227 -0
- package/docs/charter.B1.align.yaml +179 -0
- package/docs/charter.B2.align.yaml +200 -0
- package/docs/charter.B3.align.yaml +200 -0
- package/docs/charter.B4.align.yaml +188 -0
- package/docs/charter.C1.align.yaml +190 -0
- package/docs/charter.C2.align.yaml +202 -0
- package/docs/charter.C3.align.yaml +211 -0
- package/docs/charter.C4.align.yaml +263 -0
- package/docs/charter.C5.align.yaml +220 -0
- package/docs/charter.D1.align.yaml +190 -0
- package/docs/charter.D2.align.yaml +234 -0
- package/docs/charter.D3.align.yaml +206 -0
- package/docs/charter.E-Docs.align.yaml +294 -0
- package/docs/charter.F1.align.yaml +193 -0
- package/docs/charter.F2.align.yaml +248 -0
- package/docs/charter.F3.align.yaml +287 -0
- package/docs/charter.G.align.yaml +174 -0
- package/docs/charter.align.yaml +111 -0
- package/docs/examples/session-report-usage.md +449 -0
- package/docs/maintenance.md +682 -0
- package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
- package/docs/setup-guide.md +775 -0
- package/docs/tasks.A1.atomize.md +296 -0
- package/docs/tasks.A2.atomize.md +408 -0
- package/docs/tasks.A3.atomize.md +564 -0
- package/docs/tasks.A4.atomize.md +496 -0
- package/docs/tasks.B1.atomize.md +352 -0
- package/docs/tasks.B2.atomize.md +561 -0
- package/docs/tasks.B3.atomize.md +508 -0
- package/docs/tasks.B4.atomize.md +504 -0
- package/docs/tasks.C1.atomize.md +540 -0
- package/docs/tasks.C2.atomize.md +665 -0
- package/docs/tasks.C3.atomize.md +745 -0
- package/docs/tasks.C4.atomize.md +908 -0
- package/docs/tasks.C5.atomize.md +755 -0
- package/docs/tasks.D1.atomize.md +547 -0
- package/docs/tasks.D2.atomize.md +619 -0
- package/docs/tasks.D3.atomize.md +790 -0
- package/docs/tasks.E-Docs.atomize.md +1204 -0
- package/docs/tasks.atomize.md +189 -0
- package/docs/troubleshooting.md +855 -0
- package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
- package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226API/345/256/214/346/225/264/346/226/207/346/241/243.md +894 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226/345/256/214/346/225/264/346/223/215/344/275/234/346/211/213/345/206/214.md +1885 -0
- package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
- package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1454 @@
|
|
|
1
|
+
# Element API
|
|
2
|
+
|
|
3
|
+
> Element 工具提供元素级别的交互操作、属性获取和组件特定功能,是自动化测试的核心执行层。
|
|
4
|
+
|
|
5
|
+
## 工具列表
|
|
6
|
+
|
|
7
|
+
### 基础交互(3 个工具)
|
|
8
|
+
|
|
9
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
10
|
+
|---------|------|----------|
|
|
11
|
+
| `element_tap` | 点击元素 | 按钮点击、链接跳转 |
|
|
12
|
+
| `element_longpress` | 长按元素 | 长按菜单触发 |
|
|
13
|
+
| `element_input` | 输入文本 | 表单填写 |
|
|
14
|
+
|
|
15
|
+
### 获取信息(7 个工具)
|
|
16
|
+
|
|
17
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
18
|
+
|---------|------|----------|
|
|
19
|
+
| `element_get_text` | 获取文本内容 | 文本验证 |
|
|
20
|
+
| `element_get_value` | 获取输入框值 | 表单数据验证 |
|
|
21
|
+
| `element_get_attribute` | 获取 HTML 属性 | 属性检查 |
|
|
22
|
+
| `element_get_property` | 获取 DOM 属性 | 属性对象访问 |
|
|
23
|
+
| `element_get_style` | 获取样式值 | 样式验证 |
|
|
24
|
+
| `element_get_size` | 获取元素尺寸 | 布局验证 |
|
|
25
|
+
| `element_get_offset` | 获取元素偏移 | 位置验证 |
|
|
26
|
+
|
|
27
|
+
### 触摸事件(4 个工具)
|
|
28
|
+
|
|
29
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
30
|
+
|---------|------|----------|
|
|
31
|
+
| `element_touchstart` | 触摸开始 | 自定义手势起始 |
|
|
32
|
+
| `element_touchmove` | 触摸移动 | 拖动、滑动操作 |
|
|
33
|
+
| `element_touchend` | 触摸结束 | 手势完成 |
|
|
34
|
+
| `element_trigger` | 触发事件 | 自定义事件模拟 |
|
|
35
|
+
|
|
36
|
+
### 滚动操作(3 个工具 - ScrollView)
|
|
37
|
+
|
|
38
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
39
|
+
|---------|------|----------|
|
|
40
|
+
| `element_scroll_to` | 滚动到指定位置 | 定位滚动 |
|
|
41
|
+
| `element_scroll_width` | 获取滚动宽度 | 横向滚动范围检查 |
|
|
42
|
+
| `element_scroll_height` | 获取滚动高度 | 纵向滚动范围检查 |
|
|
43
|
+
|
|
44
|
+
### 组件特定操作(6 个工具)
|
|
45
|
+
|
|
46
|
+
| 工具名称 | 描述 | 组件类型 |
|
|
47
|
+
|---------|------|----------|
|
|
48
|
+
| `element_swipe_to` | 滑动到指定索引 | Swiper |
|
|
49
|
+
| `element_move_to` | 移动到指定位置 | MovableView |
|
|
50
|
+
| `element_slide_to` | 滑动到指定值 | Slider |
|
|
51
|
+
| `element_call_context_method` | 调用上下文方法 | ContextElement |
|
|
52
|
+
| `element_set_data` | 设置自定义组件数据 | CustomElement |
|
|
53
|
+
| `element_call_method` | 调用自定义组件方法 | CustomElement |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 基础交互
|
|
58
|
+
|
|
59
|
+
### element_tap
|
|
60
|
+
|
|
61
|
+
点击元素(模拟用户点击操作)。
|
|
62
|
+
|
|
63
|
+
#### 参数
|
|
64
|
+
|
|
65
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
66
|
+
|--------|------|------|--------|------|
|
|
67
|
+
| `refId` | string | ✅ | - | 元素引用 ID(来自 `page_query`) |
|
|
68
|
+
|
|
69
|
+
#### 返回值
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
{
|
|
73
|
+
success: true,
|
|
74
|
+
message: "Element tapped: elem_abc123"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### 错误处理
|
|
79
|
+
|
|
80
|
+
- **元素不存在**: `Error: Element not found with refId: {refId}. Use page_query to get element reference first.`
|
|
81
|
+
- **点击失败**: `Error: Tap failed: {reason}`
|
|
82
|
+
|
|
83
|
+
#### 使用示例
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// 示例 1: 点击按钮
|
|
87
|
+
const btn = await page_query({
|
|
88
|
+
selector: ".submit-btn",
|
|
89
|
+
save: true
|
|
90
|
+
})
|
|
91
|
+
await element_tap({ refId: btn.refId })
|
|
92
|
+
|
|
93
|
+
// 示例 2: 点击列表项
|
|
94
|
+
const items = await page_query_all({
|
|
95
|
+
selector: ".product-item",
|
|
96
|
+
save: true
|
|
97
|
+
})
|
|
98
|
+
// 点击第 3 个商品
|
|
99
|
+
await element_tap({ refId: items.elements[2].refId })
|
|
100
|
+
|
|
101
|
+
// 示例 3: 点击后验证跳转
|
|
102
|
+
await element_tap({ refId: btn.refId })
|
|
103
|
+
await page_wait_for({
|
|
104
|
+
selector: ".detail-page",
|
|
105
|
+
timeout: 2000
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// 示例 4: 连续点击
|
|
109
|
+
await element_tap({ refId: plusBtn.refId }) // 数量 +1
|
|
110
|
+
await element_tap({ refId: plusBtn.refId }) // 数量 +2
|
|
111
|
+
const count = await element_get_text({ refId: countDisplay.refId })
|
|
112
|
+
console.log(count.text) // "2"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### 注意事项
|
|
116
|
+
|
|
117
|
+
- 💡 **必需引用**: 必须先使用 `page_query` 获取元素引用
|
|
118
|
+
- 💡 **等待渲染**: 确保元素已渲染完成,否则使用 `page_wait_for`
|
|
119
|
+
- ⚠️ **事件触发**: 会触发小程序的 tap 事件和相关生命周期
|
|
120
|
+
|
|
121
|
+
#### 相关工具
|
|
122
|
+
|
|
123
|
+
- [`element_longpress`](#element_longpress) - 长按元素
|
|
124
|
+
- [`page_query`](./page.md#page_query) - 查询元素获取 refId
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### element_longpress
|
|
129
|
+
|
|
130
|
+
长按元素(模拟用户长按操作)。
|
|
131
|
+
|
|
132
|
+
#### 参数
|
|
133
|
+
|
|
134
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
135
|
+
|--------|------|------|--------|------|
|
|
136
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
137
|
+
|
|
138
|
+
#### 返回值
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
{
|
|
142
|
+
success: true,
|
|
143
|
+
message: "Element long pressed: elem_abc123"
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### 使用示例
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// 示例 1: 长按触发菜单
|
|
151
|
+
const item = await page_query({
|
|
152
|
+
selector: ".message-item",
|
|
153
|
+
save: true
|
|
154
|
+
})
|
|
155
|
+
await element_longpress({ refId: item.refId })
|
|
156
|
+
await page_wait_for({
|
|
157
|
+
selector: ".context-menu",
|
|
158
|
+
timeout: 1000
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// 示例 2: 长按删除
|
|
162
|
+
await element_longpress({ refId: item.refId })
|
|
163
|
+
await element_tap({ selector: ".delete-btn" })
|
|
164
|
+
await assert_not_exists({ selector: ".message-item" })
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### 注意事项
|
|
168
|
+
|
|
169
|
+
- 💡 **长按时长**: 默认长按时长由小程序组件决定(通常 350ms)
|
|
170
|
+
- ⚠️ **事件触发**: 会触发 longpress 事件,不会触发 tap 事件
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### element_input
|
|
175
|
+
|
|
176
|
+
向输入框或文本域输入文本。
|
|
177
|
+
|
|
178
|
+
#### 参数
|
|
179
|
+
|
|
180
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
181
|
+
|--------|------|------|--------|------|
|
|
182
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
183
|
+
| `value` | string | ✅ | - | 要输入的文本内容 |
|
|
184
|
+
|
|
185
|
+
#### 返回值
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
{
|
|
189
|
+
success: true,
|
|
190
|
+
message: "Text input to element: elem_abc123"
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### 错误处理
|
|
195
|
+
|
|
196
|
+
- **元素不可输入**: `Error: Input failed: Element is not an input or textarea`
|
|
197
|
+
|
|
198
|
+
#### 使用示例
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
// 示例 1: 表单填写
|
|
202
|
+
const username = await page_query({
|
|
203
|
+
selector: "#username",
|
|
204
|
+
save: true
|
|
205
|
+
})
|
|
206
|
+
const password = await page_query({
|
|
207
|
+
selector: "#password",
|
|
208
|
+
save: true
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
await element_input({
|
|
212
|
+
refId: username.refId,
|
|
213
|
+
value: "testuser"
|
|
214
|
+
})
|
|
215
|
+
await element_input({
|
|
216
|
+
refId: password.refId,
|
|
217
|
+
value: "password123"
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
await element_tap({ selector: ".login-btn" })
|
|
221
|
+
|
|
222
|
+
// 示例 2: 搜索操作
|
|
223
|
+
const searchInput = await page_query({
|
|
224
|
+
selector: ".search-input",
|
|
225
|
+
save: true
|
|
226
|
+
})
|
|
227
|
+
await element_input({
|
|
228
|
+
refId: searchInput.refId,
|
|
229
|
+
value: "iPhone 15"
|
|
230
|
+
})
|
|
231
|
+
await element_tap({ selector: ".search-btn" })
|
|
232
|
+
|
|
233
|
+
// 示例 3: 覆盖已有内容
|
|
234
|
+
// 注意:element_input 会覆盖原有内容,不是追加
|
|
235
|
+
await element_input({
|
|
236
|
+
refId: input.refId,
|
|
237
|
+
value: "新内容"
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// 示例 4: 输入后验证
|
|
241
|
+
await element_input({
|
|
242
|
+
refId: input.refId,
|
|
243
|
+
value: "测试文本"
|
|
244
|
+
})
|
|
245
|
+
const result = await element_get_value({ refId: input.refId })
|
|
246
|
+
console.log(result.value) // "测试文本"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### 注意事项
|
|
250
|
+
|
|
251
|
+
- ⚠️ **仅限输入组件**: 仅适用于 `input` 和 `textarea` 组件
|
|
252
|
+
- 💡 **覆盖内容**: 会覆盖原有内容,不是追加
|
|
253
|
+
- 💡 **触发事件**: 会触发 input 和 change 事件
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## 获取信息
|
|
258
|
+
|
|
259
|
+
### element_get_text
|
|
260
|
+
|
|
261
|
+
获取元素的文本内容(innerText)。
|
|
262
|
+
|
|
263
|
+
#### 参数
|
|
264
|
+
|
|
265
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
266
|
+
|--------|------|------|--------|------|
|
|
267
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
268
|
+
|
|
269
|
+
#### 返回值
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
{
|
|
273
|
+
success: true,
|
|
274
|
+
message: "Element text retrieved",
|
|
275
|
+
text: "Hello World"
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### 使用示例
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// 示例 1: 获取标题文本
|
|
283
|
+
const title = await page_query({
|
|
284
|
+
selector: ".page-title",
|
|
285
|
+
save: true
|
|
286
|
+
})
|
|
287
|
+
const result = await element_get_text({ refId: title.refId })
|
|
288
|
+
console.log(result.text) // "商品详情"
|
|
289
|
+
|
|
290
|
+
// 示例 2: 获取列表所有文本
|
|
291
|
+
const items = await page_query_all({
|
|
292
|
+
selector: ".item-title",
|
|
293
|
+
save: true
|
|
294
|
+
})
|
|
295
|
+
const titles = []
|
|
296
|
+
for (const item of items.elements) {
|
|
297
|
+
const text = await element_get_text({ refId: item.refId })
|
|
298
|
+
titles.push(text.text)
|
|
299
|
+
}
|
|
300
|
+
console.log("商品列表:", titles)
|
|
301
|
+
|
|
302
|
+
// 示例 3: 文本验证
|
|
303
|
+
const price = await page_query({
|
|
304
|
+
selector: ".price",
|
|
305
|
+
save: true
|
|
306
|
+
})
|
|
307
|
+
const result = await element_get_text({ refId: price.refId })
|
|
308
|
+
if (result.text.includes("¥")) {
|
|
309
|
+
console.log("价格格式正确")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// 示例 4: 获取嵌套文本
|
|
313
|
+
const card = await page_query({
|
|
314
|
+
selector: ".user-card",
|
|
315
|
+
save: true
|
|
316
|
+
})
|
|
317
|
+
const text = await element_get_text({ refId: card.refId })
|
|
318
|
+
console.log(text.text) // 包含所有子元素文本
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### 注意事项
|
|
322
|
+
|
|
323
|
+
- 💡 **包含子元素**: 返回的文本包含所有子元素的文本
|
|
324
|
+
- 💡 **空白字符**: 可能包含前后空白字符
|
|
325
|
+
- ⚠️ **不可见元素**: 即使元素不可见也能获取文本
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### element_get_value
|
|
330
|
+
|
|
331
|
+
获取输入框或文本域的当前值。
|
|
332
|
+
|
|
333
|
+
#### 参数
|
|
334
|
+
|
|
335
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
336
|
+
|--------|------|------|--------|------|
|
|
337
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
338
|
+
|
|
339
|
+
#### 返回值
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
{
|
|
343
|
+
success: true,
|
|
344
|
+
message: "Element value retrieved",
|
|
345
|
+
value: "user input text"
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### 使用示例
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
// 示例 1: 获取输入框值
|
|
353
|
+
const input = await page_query({
|
|
354
|
+
selector: "#email",
|
|
355
|
+
save: true
|
|
356
|
+
})
|
|
357
|
+
const result = await element_get_value({ refId: input.refId })
|
|
358
|
+
console.log("邮箱:", result.value)
|
|
359
|
+
|
|
360
|
+
// 示例 2: 验证表单数据
|
|
361
|
+
await element_input({ refId: username.refId, value: "alice" })
|
|
362
|
+
const check = await element_get_value({ refId: username.refId })
|
|
363
|
+
if (check.value === "alice") {
|
|
364
|
+
console.log("✅ 输入成功")
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// 示例 3: 获取初始值
|
|
368
|
+
// 未输入时返回空字符串或默认值
|
|
369
|
+
const result = await element_get_value({ refId: input.refId })
|
|
370
|
+
console.log(result.value) // "" 或默认值
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### 注意事项
|
|
374
|
+
|
|
375
|
+
- ⚠️ **仅限输入组件**: 仅适用于 `input`, `textarea`, `picker` 等表单组件
|
|
376
|
+
- 💡 **非文本元素**: 对于非表单元素,使用 `element_get_text`
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
### element_get_attribute
|
|
381
|
+
|
|
382
|
+
获取元素的 HTML 属性值(attribute)。
|
|
383
|
+
|
|
384
|
+
#### 参数
|
|
385
|
+
|
|
386
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
387
|
+
|--------|------|------|--------|------|
|
|
388
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
389
|
+
| `name` | string | ✅ | - | 属性名称(如 `class`, `id`, `data-id`) |
|
|
390
|
+
|
|
391
|
+
#### 返回值
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
{
|
|
395
|
+
success: true,
|
|
396
|
+
message: "Attribute \"class\" retrieved",
|
|
397
|
+
value: "btn primary"
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### 使用示例
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
// 示例 1: 获取 class 属性
|
|
405
|
+
const btn = await page_query({
|
|
406
|
+
selector: ".submit-btn",
|
|
407
|
+
save: true
|
|
408
|
+
})
|
|
409
|
+
const result = await element_get_attribute({
|
|
410
|
+
refId: btn.refId,
|
|
411
|
+
name: "class"
|
|
412
|
+
})
|
|
413
|
+
console.log(result.value) // "submit-btn primary"
|
|
414
|
+
|
|
415
|
+
// 示例 2: 获取自定义属性
|
|
416
|
+
const item = await page_query({
|
|
417
|
+
selector: ".product-item",
|
|
418
|
+
save: true
|
|
419
|
+
})
|
|
420
|
+
const productId = await element_get_attribute({
|
|
421
|
+
refId: item.refId,
|
|
422
|
+
name: "data-id"
|
|
423
|
+
})
|
|
424
|
+
console.log("商品 ID:", productId.value)
|
|
425
|
+
|
|
426
|
+
// 示例 3: 检查属性是否存在
|
|
427
|
+
const result = await element_get_attribute({
|
|
428
|
+
refId: el.refId,
|
|
429
|
+
name: "disabled"
|
|
430
|
+
})
|
|
431
|
+
if (result.value !== null) {
|
|
432
|
+
console.log("按钮已禁用")
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### 注意事项
|
|
437
|
+
|
|
438
|
+
- 💡 **Attribute vs Property**: 属性(attribute)是 HTML 标签上的,属性(property)是 DOM 对象的
|
|
439
|
+
- 💡 **不存在返回 null**: 如果属性不存在,返回 `null`
|
|
440
|
+
- 💡 **小程序专有属性**: 支持小程序组件的自定义属性(如 `data-*`)
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
### element_get_property
|
|
445
|
+
|
|
446
|
+
获取元素的 DOM 属性值(property)。
|
|
447
|
+
|
|
448
|
+
#### 参数
|
|
449
|
+
|
|
450
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
451
|
+
|--------|------|------|--------|------|
|
|
452
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
453
|
+
| `name` | string | ✅ | - | 属性名称(如 `value`, `checked`, `dataset`) |
|
|
454
|
+
|
|
455
|
+
#### 返回值
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
{
|
|
459
|
+
success: true,
|
|
460
|
+
message: "Property \"checked\" retrieved",
|
|
461
|
+
value: true // 可能是任意类型
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
#### 使用示例
|
|
466
|
+
|
|
467
|
+
```javascript
|
|
468
|
+
// 示例 1: 获取 checkbox 状态
|
|
469
|
+
const checkbox = await page_query({
|
|
470
|
+
selector: "checkbox",
|
|
471
|
+
save: true
|
|
472
|
+
})
|
|
473
|
+
const result = await element_get_property({
|
|
474
|
+
refId: checkbox.refId,
|
|
475
|
+
name: "checked"
|
|
476
|
+
})
|
|
477
|
+
console.log("选中状态:", result.value) // true/false
|
|
478
|
+
|
|
479
|
+
// 示例 2: 获取 dataset
|
|
480
|
+
const item = await page_query({
|
|
481
|
+
selector: ".item",
|
|
482
|
+
save: true
|
|
483
|
+
})
|
|
484
|
+
const dataset = await element_get_property({
|
|
485
|
+
refId: item.refId,
|
|
486
|
+
name: "dataset"
|
|
487
|
+
})
|
|
488
|
+
console.log("数据集:", dataset.value) // { id: "123", type: "product" }
|
|
489
|
+
|
|
490
|
+
// 示例 3: 获取 value(property 形式)
|
|
491
|
+
const input = await page_query({
|
|
492
|
+
selector: "input",
|
|
493
|
+
save: true
|
|
494
|
+
})
|
|
495
|
+
const result = await element_get_property({
|
|
496
|
+
refId: input.refId,
|
|
497
|
+
name: "value"
|
|
498
|
+
})
|
|
499
|
+
console.log(result.value)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
#### 注意事项
|
|
503
|
+
|
|
504
|
+
- 💡 **返回类型**: 可能返回任意 JavaScript 类型(string, number, boolean, object, array)
|
|
505
|
+
- 💡 **与 attribute 的区别**: property 是 DOM 对象的运行时状态,attribute 是 HTML 标签的静态定义
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
### element_get_style
|
|
510
|
+
|
|
511
|
+
获取元素的样式值。
|
|
512
|
+
|
|
513
|
+
#### 参数
|
|
514
|
+
|
|
515
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
516
|
+
|--------|------|------|--------|------|
|
|
517
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
518
|
+
| `name` | string | ✅ | - | 样式属性名(如 `color`, `fontSize`, `display`) |
|
|
519
|
+
|
|
520
|
+
#### 返回值
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
{
|
|
524
|
+
success: true,
|
|
525
|
+
message: "Style \"color\" retrieved",
|
|
526
|
+
value: "rgb(255, 0, 0)"
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### 使用示例
|
|
531
|
+
|
|
532
|
+
```javascript
|
|
533
|
+
// 示例 1: 获取颜色
|
|
534
|
+
const title = await page_query({
|
|
535
|
+
selector: ".title",
|
|
536
|
+
save: true
|
|
537
|
+
})
|
|
538
|
+
const color = await element_get_style({
|
|
539
|
+
refId: title.refId,
|
|
540
|
+
name: "color"
|
|
541
|
+
})
|
|
542
|
+
console.log("标题颜色:", color.value) // "rgb(255, 0, 0)"
|
|
543
|
+
|
|
544
|
+
// 示例 2: 检查显示状态
|
|
545
|
+
const modal = await page_query({
|
|
546
|
+
selector: ".modal",
|
|
547
|
+
save: true
|
|
548
|
+
})
|
|
549
|
+
const display = await element_get_style({
|
|
550
|
+
refId: modal.refId,
|
|
551
|
+
name: "display"
|
|
552
|
+
})
|
|
553
|
+
if (display.value === "none") {
|
|
554
|
+
console.log("模态框已隐藏")
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// 示例 3: 获取字体大小
|
|
558
|
+
const fontSize = await element_get_style({
|
|
559
|
+
refId: el.refId,
|
|
560
|
+
name: "fontSize"
|
|
561
|
+
})
|
|
562
|
+
console.log(fontSize.value) // "16px"
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
#### 注意事项
|
|
566
|
+
|
|
567
|
+
- 💡 **计算样式**: 返回的是计算后的样式值,包含继承和默认值
|
|
568
|
+
- 💡 **单位**: 数值类型样式会包含单位(如 `16px`, `1.5em`)
|
|
569
|
+
- ⚠️ **驼峰命名**: 使用 JavaScript 驼峰命名(`fontSize` 而非 `font-size`)
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
### element_get_size
|
|
574
|
+
|
|
575
|
+
获取元素的宽度和高度(尺寸)。
|
|
576
|
+
|
|
577
|
+
#### 参数
|
|
578
|
+
|
|
579
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
580
|
+
|--------|------|------|--------|------|
|
|
581
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
582
|
+
|
|
583
|
+
#### 返回值
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
{
|
|
587
|
+
success: true,
|
|
588
|
+
message: "Element size retrieved",
|
|
589
|
+
size: {
|
|
590
|
+
width: 375, // 宽度(px)
|
|
591
|
+
height: 50 // 高度(px)
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
#### 使用示例
|
|
597
|
+
|
|
598
|
+
```javascript
|
|
599
|
+
// 示例 1: 获取按钮尺寸
|
|
600
|
+
const btn = await page_query({
|
|
601
|
+
selector: ".submit-btn",
|
|
602
|
+
save: true
|
|
603
|
+
})
|
|
604
|
+
const size = await element_get_size({ refId: btn.refId })
|
|
605
|
+
console.log(`按钮尺寸: ${size.size.width}x${size.size.height}`)
|
|
606
|
+
|
|
607
|
+
// 示例 2: 验证布局
|
|
608
|
+
const card = await page_query({
|
|
609
|
+
selector: ".card",
|
|
610
|
+
save: true
|
|
611
|
+
})
|
|
612
|
+
const { size } = await element_get_size({ refId: card.refId })
|
|
613
|
+
if (size.width < 300) {
|
|
614
|
+
console.warn("卡片宽度不足")
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// 示例 3: 计算宽高比
|
|
618
|
+
const image = await page_query({
|
|
619
|
+
selector: ".product-image",
|
|
620
|
+
save: true
|
|
621
|
+
})
|
|
622
|
+
const { size } = await element_get_size({ refId: image.refId })
|
|
623
|
+
const ratio = size.width / size.height
|
|
624
|
+
console.log("图片宽高比:", ratio.toFixed(2))
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
#### 注意事项
|
|
628
|
+
|
|
629
|
+
- 💡 **单位**: 返回值单位为物理像素(px)
|
|
630
|
+
- 💡 **包含 padding 和 border**: 返回的是元素的外部尺寸
|
|
631
|
+
- ⚠️ **不可见元素**: 不可见元素(display: none)宽高为 0
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
635
|
+
### element_get_offset
|
|
636
|
+
|
|
637
|
+
获取元素相对于页面的偏移位置。
|
|
638
|
+
|
|
639
|
+
#### 参数
|
|
640
|
+
|
|
641
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
642
|
+
|--------|------|------|--------|------|
|
|
643
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
644
|
+
|
|
645
|
+
#### 返回值
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
{
|
|
649
|
+
success: true,
|
|
650
|
+
message: "Element offset retrieved",
|
|
651
|
+
offset: {
|
|
652
|
+
left: 20, // 左偏移(px)
|
|
653
|
+
top: 100 // 上偏移(px)
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
#### 使用示例
|
|
659
|
+
|
|
660
|
+
```javascript
|
|
661
|
+
// 示例 1: 获取元素位置
|
|
662
|
+
const element = await page_query({
|
|
663
|
+
selector: ".floating-btn",
|
|
664
|
+
save: true
|
|
665
|
+
})
|
|
666
|
+
const offset = await element_get_offset({ refId: element.refId })
|
|
667
|
+
console.log(`位置: (${offset.offset.left}, ${offset.offset.top})`)
|
|
668
|
+
|
|
669
|
+
// 示例 2: 判断元素是否在视口内
|
|
670
|
+
const { offset } = await element_get_offset({ refId: el.refId })
|
|
671
|
+
const { size } = await page_get_size()
|
|
672
|
+
const isVisible = offset.top >= 0 && offset.top < size.height
|
|
673
|
+
console.log("是否可见:", isVisible)
|
|
674
|
+
|
|
675
|
+
// 示例 3: 计算两个元素的相对位置
|
|
676
|
+
const offset1 = await element_get_offset({ refId: el1.refId })
|
|
677
|
+
const offset2 = await element_get_offset({ refId: el2.refId })
|
|
678
|
+
const distance = Math.abs(offset2.offset.top - offset1.offset.top)
|
|
679
|
+
console.log("垂直距离:", distance)
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
#### 注意事项
|
|
683
|
+
|
|
684
|
+
- 💡 **相对于页面**: 偏移量是相对于页面左上角,不是视口
|
|
685
|
+
- 💡 **滚动影响**: 不受页面滚动影响(始终相对页面原点)
|
|
686
|
+
- ⚠️ **定位元素**: position: fixed 元素的 offset 可能不符合预期
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## 触摸事件
|
|
691
|
+
|
|
692
|
+
### element_touchstart
|
|
693
|
+
|
|
694
|
+
触发触摸开始事件。
|
|
695
|
+
|
|
696
|
+
#### 参数
|
|
697
|
+
|
|
698
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
699
|
+
|--------|------|------|--------|------|
|
|
700
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
701
|
+
| `touches` | array | ✅ | - | 当前屏幕上的触摸点数组 |
|
|
702
|
+
| `changedTouches` | array | ✅ | - | 变化的触摸点数组 |
|
|
703
|
+
|
|
704
|
+
#### 返回值
|
|
705
|
+
|
|
706
|
+
```typescript
|
|
707
|
+
{
|
|
708
|
+
success: true,
|
|
709
|
+
message: "Touch start on element: elem_abc123"
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
#### 使用示例
|
|
714
|
+
|
|
715
|
+
```javascript
|
|
716
|
+
// 示例 1: 单点触摸开始
|
|
717
|
+
const element = await page_query({
|
|
718
|
+
selector: ".canvas",
|
|
719
|
+
save: true
|
|
720
|
+
})
|
|
721
|
+
await element_touchstart({
|
|
722
|
+
refId: element.refId,
|
|
723
|
+
touches: [{ identifier: 0, pageX: 100, pageY: 200 }],
|
|
724
|
+
changedTouches: [{ identifier: 0, pageX: 100, pageY: 200 }]
|
|
725
|
+
})
|
|
726
|
+
|
|
727
|
+
// 示例 2: 配合 touchmove 和 touchend 实现滑动
|
|
728
|
+
await element_touchstart({
|
|
729
|
+
refId: el.refId,
|
|
730
|
+
touches: [{ identifier: 0, pageX: 100, pageY: 200 }],
|
|
731
|
+
changedTouches: [{ identifier: 0, pageX: 100, pageY: 200 }]
|
|
732
|
+
})
|
|
733
|
+
await element_touchmove({
|
|
734
|
+
refId: el.refId,
|
|
735
|
+
touches: [{ identifier: 0, pageX: 100, pageY: 100 }],
|
|
736
|
+
changedTouches: [{ identifier: 0, pageX: 100, pageY: 100 }]
|
|
737
|
+
})
|
|
738
|
+
await element_touchend({
|
|
739
|
+
refId: el.refId,
|
|
740
|
+
touches: [],
|
|
741
|
+
changedTouches: [{ identifier: 0, pageX: 100, pageY: 100 }]
|
|
742
|
+
})
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
#### 注意事项
|
|
746
|
+
|
|
747
|
+
- 💡 **触摸点格式**: `{ identifier: number, pageX: number, pageY: number }`
|
|
748
|
+
- 💡 **多点触摸**: `touches` 可包含多个触摸点
|
|
749
|
+
- ⚠️ **必须配对**: touchstart 必须与 touchmove/touchend 配对使用
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
### element_touchmove
|
|
754
|
+
|
|
755
|
+
触发触摸移动事件。
|
|
756
|
+
|
|
757
|
+
#### 参数
|
|
758
|
+
|
|
759
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
760
|
+
|--------|------|------|--------|------|
|
|
761
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
762
|
+
| `touches` | array | ✅ | - | 当前屏幕上的触摸点数组 |
|
|
763
|
+
| `changedTouches` | array | ✅ | - | 变化的触摸点数组 |
|
|
764
|
+
|
|
765
|
+
#### 使用示例
|
|
766
|
+
|
|
767
|
+
```javascript
|
|
768
|
+
// 示例 1: 拖动元素
|
|
769
|
+
await element_touchstart({ refId, touches: [{ identifier: 0, pageX: 100, pageY: 100 }], changedTouches: [{ identifier: 0, pageX: 100, pageY: 100 }] })
|
|
770
|
+
for (let i = 0; i < 10; i++) {
|
|
771
|
+
await element_touchmove({
|
|
772
|
+
refId,
|
|
773
|
+
touches: [{ identifier: 0, pageX: 100 + i * 10, pageY: 100 }],
|
|
774
|
+
changedTouches: [{ identifier: 0, pageX: 100 + i * 10, pageY: 100 }]
|
|
775
|
+
})
|
|
776
|
+
}
|
|
777
|
+
await element_touchend({ refId, touches: [], changedTouches: [{ identifier: 0, pageX: 200, pageY: 100 }] })
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
### element_touchend
|
|
783
|
+
|
|
784
|
+
触发触摸结束事件。
|
|
785
|
+
|
|
786
|
+
#### 参数
|
|
787
|
+
|
|
788
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
789
|
+
|--------|------|------|--------|------|
|
|
790
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
791
|
+
| `touches` | array | ✅ | - | 当前屏幕上的触摸点数组(通常为空) |
|
|
792
|
+
| `changedTouches` | array | ✅ | - | 变化的触摸点数组 |
|
|
793
|
+
|
|
794
|
+
#### 使用示例
|
|
795
|
+
|
|
796
|
+
```javascript
|
|
797
|
+
// 示例 1: 完成触摸手势
|
|
798
|
+
await element_touchend({
|
|
799
|
+
refId: el.refId,
|
|
800
|
+
touches: [], // 所有手指离开屏幕
|
|
801
|
+
changedTouches: [{ identifier: 0, pageX: 200, pageY: 100 }]
|
|
802
|
+
})
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
---
|
|
806
|
+
|
|
807
|
+
### element_trigger
|
|
808
|
+
|
|
809
|
+
触发自定义事件。
|
|
810
|
+
|
|
811
|
+
#### 参数
|
|
812
|
+
|
|
813
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
814
|
+
|--------|------|------|--------|------|
|
|
815
|
+
| `refId` | string | ✅ | - | 元素引用 ID |
|
|
816
|
+
| `type` | string | ✅ | - | 事件类型(如 `change`, `custom-event`) |
|
|
817
|
+
| `detail` | object | ⭐ | {} | 事件详细数据 |
|
|
818
|
+
|
|
819
|
+
#### 返回值
|
|
820
|
+
|
|
821
|
+
```typescript
|
|
822
|
+
{
|
|
823
|
+
success: true,
|
|
824
|
+
message: "Event \"change\" triggered on element: elem_abc123"
|
|
825
|
+
}
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
#### 使用示例
|
|
829
|
+
|
|
830
|
+
```javascript
|
|
831
|
+
// 示例 1: 触发 change 事件
|
|
832
|
+
const picker = await page_query({
|
|
833
|
+
selector: "picker",
|
|
834
|
+
save: true
|
|
835
|
+
})
|
|
836
|
+
await element_trigger({
|
|
837
|
+
refId: picker.refId,
|
|
838
|
+
type: "change",
|
|
839
|
+
detail: { value: 2 }
|
|
840
|
+
})
|
|
841
|
+
|
|
842
|
+
// 示例 2: 触发自定义事件
|
|
843
|
+
const component = await page_query({
|
|
844
|
+
selector: ".custom-component",
|
|
845
|
+
save: true
|
|
846
|
+
})
|
|
847
|
+
await element_trigger({
|
|
848
|
+
refId: component.refId,
|
|
849
|
+
type: "custom-event",
|
|
850
|
+
detail: { action: "submit", data: { id: 123 } }
|
|
851
|
+
})
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
#### 注意事项
|
|
855
|
+
|
|
856
|
+
- 💡 **小程序事件**: 支持所有小程序标准事件(tap, change, input 等)
|
|
857
|
+
- 💡 **自定义事件**: 可触发组件的自定义事件
|
|
858
|
+
- ⚠️ **事件冒泡**: 会按照小程序事件系统冒泡
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
## 滚动操作(ScrollView)
|
|
863
|
+
|
|
864
|
+
### element_scroll_to
|
|
865
|
+
|
|
866
|
+
滚动到指定位置(仅限 ScrollView 组件)。
|
|
867
|
+
|
|
868
|
+
#### 参数
|
|
869
|
+
|
|
870
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
871
|
+
|--------|------|------|--------|------|
|
|
872
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 ScrollView) |
|
|
873
|
+
| `x` | number | ✅ | - | 横向滚动位置(px) |
|
|
874
|
+
| `y` | number | ✅ | - | 纵向滚动位置(px) |
|
|
875
|
+
|
|
876
|
+
#### 返回值
|
|
877
|
+
|
|
878
|
+
```typescript
|
|
879
|
+
{
|
|
880
|
+
success: true,
|
|
881
|
+
message: "Scrolled to (0, 300)"
|
|
882
|
+
}
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
#### 使用示例
|
|
886
|
+
|
|
887
|
+
```javascript
|
|
888
|
+
// 示例 1: 滚动到顶部
|
|
889
|
+
const scrollView = await page_query({
|
|
890
|
+
selector: "scroll-view",
|
|
891
|
+
save: true
|
|
892
|
+
})
|
|
893
|
+
await element_scroll_to({
|
|
894
|
+
refId: scrollView.refId,
|
|
895
|
+
x: 0,
|
|
896
|
+
y: 0
|
|
897
|
+
})
|
|
898
|
+
|
|
899
|
+
// 示例 2: 滚动到底部
|
|
900
|
+
const height = await element_scroll_height({ refId: scrollView.refId })
|
|
901
|
+
await element_scroll_to({
|
|
902
|
+
refId: scrollView.refId,
|
|
903
|
+
x: 0,
|
|
904
|
+
y: height.height
|
|
905
|
+
})
|
|
906
|
+
|
|
907
|
+
// 示例 3: 横向滚动
|
|
908
|
+
await element_scroll_to({
|
|
909
|
+
refId: scrollView.refId,
|
|
910
|
+
x: 300,
|
|
911
|
+
y: 0
|
|
912
|
+
})
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
#### 注意事项
|
|
916
|
+
|
|
917
|
+
- ⚠️ **仅 ScrollView**: 仅适用于 `scroll-view` 组件
|
|
918
|
+
- 💡 **超出范围**: 如果滚动位置超出范围,会滚动到最大/最小值
|
|
919
|
+
- 💡 **动画**: 滚动有动画效果,建议使用 `page_wait_for` 等待
|
|
920
|
+
|
|
921
|
+
---
|
|
922
|
+
|
|
923
|
+
### element_scroll_width
|
|
924
|
+
|
|
925
|
+
获取 ScrollView 的滚动宽度(内容总宽度)。
|
|
926
|
+
|
|
927
|
+
#### 参数
|
|
928
|
+
|
|
929
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
930
|
+
|--------|------|------|--------|------|
|
|
931
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 ScrollView) |
|
|
932
|
+
|
|
933
|
+
#### 返回值
|
|
934
|
+
|
|
935
|
+
```typescript
|
|
936
|
+
{
|
|
937
|
+
success: true,
|
|
938
|
+
message: "Scroll width retrieved",
|
|
939
|
+
width: 800 // 内容总宽度(px)
|
|
940
|
+
}
|
|
941
|
+
```
|
|
942
|
+
|
|
943
|
+
#### 使用示例
|
|
944
|
+
|
|
945
|
+
```javascript
|
|
946
|
+
// 示例 1: 获取可滚动宽度
|
|
947
|
+
const scrollView = await page_query({
|
|
948
|
+
selector: "scroll-view",
|
|
949
|
+
save: true
|
|
950
|
+
})
|
|
951
|
+
const result = await element_scroll_width({ refId: scrollView.refId })
|
|
952
|
+
console.log("内容宽度:", result.width)
|
|
953
|
+
|
|
954
|
+
// 示例 2: 判断是否可滚动
|
|
955
|
+
const viewWidth = await element_get_size({ refId: scrollView.refId })
|
|
956
|
+
const contentWidth = await element_scroll_width({ refId: scrollView.refId })
|
|
957
|
+
if (contentWidth.width > viewWidth.size.width) {
|
|
958
|
+
console.log("内容超出,可以滚动")
|
|
959
|
+
}
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
---
|
|
963
|
+
|
|
964
|
+
### element_scroll_height
|
|
965
|
+
|
|
966
|
+
获取 ScrollView 的滚动高度(内容总高度)。
|
|
967
|
+
|
|
968
|
+
#### 参数
|
|
969
|
+
|
|
970
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
971
|
+
|--------|------|------|--------|------|
|
|
972
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 ScrollView) |
|
|
973
|
+
|
|
974
|
+
#### 返回值
|
|
975
|
+
|
|
976
|
+
```typescript
|
|
977
|
+
{
|
|
978
|
+
success: true,
|
|
979
|
+
message: "Scroll height retrieved",
|
|
980
|
+
height: 1200 // 内容总高度(px)
|
|
981
|
+
}
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
#### 使用示例
|
|
985
|
+
|
|
986
|
+
```javascript
|
|
987
|
+
// 示例 1: 滚动到底部
|
|
988
|
+
const height = await element_scroll_height({ refId: scrollView.refId })
|
|
989
|
+
await element_scroll_to({
|
|
990
|
+
refId: scrollView.refId,
|
|
991
|
+
x: 0,
|
|
992
|
+
y: height.height
|
|
993
|
+
})
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
## 组件特定操作
|
|
999
|
+
|
|
1000
|
+
### element_swipe_to
|
|
1001
|
+
|
|
1002
|
+
滑动到指定索引(仅限 Swiper 组件)。
|
|
1003
|
+
|
|
1004
|
+
#### 参数
|
|
1005
|
+
|
|
1006
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1007
|
+
|--------|------|------|--------|------|
|
|
1008
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 Swiper) |
|
|
1009
|
+
| `index` | number | ✅ | - | 目标索引(从 0 开始) |
|
|
1010
|
+
|
|
1011
|
+
#### 返回值
|
|
1012
|
+
|
|
1013
|
+
```typescript
|
|
1014
|
+
{
|
|
1015
|
+
success: true,
|
|
1016
|
+
message: "Swiped to index 2"
|
|
1017
|
+
}
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
#### 使用示例
|
|
1021
|
+
|
|
1022
|
+
```javascript
|
|
1023
|
+
// 示例 1: 滑动到第 3 张轮播图
|
|
1024
|
+
const swiper = await page_query({
|
|
1025
|
+
selector: "swiper",
|
|
1026
|
+
save: true
|
|
1027
|
+
})
|
|
1028
|
+
await element_swipe_to({
|
|
1029
|
+
refId: swiper.refId,
|
|
1030
|
+
index: 2 // 索引从 0 开始
|
|
1031
|
+
})
|
|
1032
|
+
|
|
1033
|
+
// 示例 2: 遍历所有轮播图
|
|
1034
|
+
for (let i = 0; i < 5; i++) {
|
|
1035
|
+
await element_swipe_to({ refId: swiper.refId, index: i })
|
|
1036
|
+
await page_wait_for({ timeout: 500 })
|
|
1037
|
+
await miniprogram_screenshot({ filename: `swiper-${i}.png` })
|
|
1038
|
+
}
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
#### 注意事项
|
|
1042
|
+
|
|
1043
|
+
- ⚠️ **仅 Swiper**: 仅适用于 `swiper` 组件
|
|
1044
|
+
- 💡 **索引范围**: 索引从 0 开始,超出范围不报错但不滚动
|
|
1045
|
+
- 💡 **动画**: 切换有动画效果
|
|
1046
|
+
|
|
1047
|
+
---
|
|
1048
|
+
|
|
1049
|
+
### element_move_to
|
|
1050
|
+
|
|
1051
|
+
移动到指定位置(仅限 MovableView 组件)。
|
|
1052
|
+
|
|
1053
|
+
#### 参数
|
|
1054
|
+
|
|
1055
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1056
|
+
|--------|------|------|--------|------|
|
|
1057
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 MovableView) |
|
|
1058
|
+
| `x` | number | ✅ | - | X 坐标(px) |
|
|
1059
|
+
| `y` | number | ✅ | - | Y 坐标(px) |
|
|
1060
|
+
|
|
1061
|
+
#### 返回值
|
|
1062
|
+
|
|
1063
|
+
```typescript
|
|
1064
|
+
{
|
|
1065
|
+
success: true,
|
|
1066
|
+
message: "Moved to (100, 200)"
|
|
1067
|
+
}
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
#### 使用示例
|
|
1071
|
+
|
|
1072
|
+
```javascript
|
|
1073
|
+
// 示例 1: 移动可拖动元素
|
|
1074
|
+
const movable = await page_query({
|
|
1075
|
+
selector: "movable-view",
|
|
1076
|
+
save: true
|
|
1077
|
+
})
|
|
1078
|
+
await element_move_to({
|
|
1079
|
+
refId: movable.refId,
|
|
1080
|
+
x: 100,
|
|
1081
|
+
y: 200
|
|
1082
|
+
})
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
---
|
|
1086
|
+
|
|
1087
|
+
### element_slide_to
|
|
1088
|
+
|
|
1089
|
+
滑动到指定值(仅限 Slider 组件)。
|
|
1090
|
+
|
|
1091
|
+
#### 参数
|
|
1092
|
+
|
|
1093
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1094
|
+
|--------|------|------|--------|------|
|
|
1095
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 Slider) |
|
|
1096
|
+
| `value` | number | ✅ | - | 目标值 |
|
|
1097
|
+
|
|
1098
|
+
#### 返回值
|
|
1099
|
+
|
|
1100
|
+
```typescript
|
|
1101
|
+
{
|
|
1102
|
+
success: true,
|
|
1103
|
+
message: "Slid to value 50"
|
|
1104
|
+
}
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
#### 使用示例
|
|
1108
|
+
|
|
1109
|
+
```javascript
|
|
1110
|
+
// 示例 1: 设置音量滑块
|
|
1111
|
+
const slider = await page_query({
|
|
1112
|
+
selector: ".volume-slider",
|
|
1113
|
+
save: true
|
|
1114
|
+
})
|
|
1115
|
+
await element_slide_to({
|
|
1116
|
+
refId: slider.refId,
|
|
1117
|
+
value: 75 // 音量设为 75%
|
|
1118
|
+
})
|
|
1119
|
+
|
|
1120
|
+
// 示例 2: 调整价格范围
|
|
1121
|
+
await element_slide_to({
|
|
1122
|
+
refId: minPrice.refId,
|
|
1123
|
+
value: 100
|
|
1124
|
+
})
|
|
1125
|
+
await element_slide_to({
|
|
1126
|
+
refId: maxPrice.refId,
|
|
1127
|
+
value: 500
|
|
1128
|
+
})
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
#### 注意事项
|
|
1132
|
+
|
|
1133
|
+
- ⚠️ **仅 Slider**: 仅适用于 `slider` 组件
|
|
1134
|
+
- 💡 **值范围**: 值必须在 slider 的 min 和 max 范围内
|
|
1135
|
+
|
|
1136
|
+
---
|
|
1137
|
+
|
|
1138
|
+
### element_call_context_method
|
|
1139
|
+
|
|
1140
|
+
调用上下文元素的方法(仅限 ContextElement)。
|
|
1141
|
+
|
|
1142
|
+
#### 参数
|
|
1143
|
+
|
|
1144
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1145
|
+
|--------|------|------|--------|------|
|
|
1146
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是 ContextElement) |
|
|
1147
|
+
| `method` | string | ✅ | - | 方法名 |
|
|
1148
|
+
| `args` | array | ⭐ | [] | 方法参数 |
|
|
1149
|
+
|
|
1150
|
+
#### 返回值
|
|
1151
|
+
|
|
1152
|
+
```typescript
|
|
1153
|
+
{
|
|
1154
|
+
success: true,
|
|
1155
|
+
message: "Context method \"play\" called successfully",
|
|
1156
|
+
result: { success: true } // 方法返回值
|
|
1157
|
+
}
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
#### 使用示例
|
|
1161
|
+
|
|
1162
|
+
```javascript
|
|
1163
|
+
// 示例 1: 调用 video 上下文方法
|
|
1164
|
+
const video = await page_query({
|
|
1165
|
+
selector: "video",
|
|
1166
|
+
save: true
|
|
1167
|
+
})
|
|
1168
|
+
await element_call_context_method({
|
|
1169
|
+
refId: video.refId,
|
|
1170
|
+
method: "play"
|
|
1171
|
+
})
|
|
1172
|
+
|
|
1173
|
+
// 示例 2: 调用 canvas 绘图方法
|
|
1174
|
+
const canvas = await page_query({
|
|
1175
|
+
selector: "canvas",
|
|
1176
|
+
save: true
|
|
1177
|
+
})
|
|
1178
|
+
await element_call_context_method({
|
|
1179
|
+
refId: canvas.refId,
|
|
1180
|
+
method: "drawImage",
|
|
1181
|
+
args: ["/images/photo.jpg", 0, 0, 100, 100]
|
|
1182
|
+
})
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
#### 注意事项
|
|
1186
|
+
|
|
1187
|
+
- ⚠️ **仅 Context 元素**: 仅适用于有上下文的元素(video, canvas, map 等)
|
|
1188
|
+
- 💡 **方法列表**: 参考小程序官方文档查看可用方法
|
|
1189
|
+
|
|
1190
|
+
---
|
|
1191
|
+
|
|
1192
|
+
### element_set_data
|
|
1193
|
+
|
|
1194
|
+
设置自定义组件的数据(仅限 CustomElement)。
|
|
1195
|
+
|
|
1196
|
+
#### 参数
|
|
1197
|
+
|
|
1198
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1199
|
+
|--------|------|------|--------|------|
|
|
1200
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是自定义组件) |
|
|
1201
|
+
| `data` | object | ✅ | - | 数据对象 |
|
|
1202
|
+
|
|
1203
|
+
#### 返回值
|
|
1204
|
+
|
|
1205
|
+
```typescript
|
|
1206
|
+
{
|
|
1207
|
+
success: true,
|
|
1208
|
+
message: "Element data updated with 2 keys"
|
|
1209
|
+
}
|
|
1210
|
+
```
|
|
1211
|
+
|
|
1212
|
+
#### 使用示例
|
|
1213
|
+
|
|
1214
|
+
```javascript
|
|
1215
|
+
// 示例 1: 设置自定义组件数据
|
|
1216
|
+
const component = await page_query({
|
|
1217
|
+
selector: "custom-component",
|
|
1218
|
+
save: true
|
|
1219
|
+
})
|
|
1220
|
+
await element_set_data({
|
|
1221
|
+
refId: component.refId,
|
|
1222
|
+
data: {
|
|
1223
|
+
title: "新标题",
|
|
1224
|
+
count: 10
|
|
1225
|
+
}
|
|
1226
|
+
})
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
---
|
|
1230
|
+
|
|
1231
|
+
### element_call_method
|
|
1232
|
+
|
|
1233
|
+
调用自定义组件的方法(仅限 CustomElement)。
|
|
1234
|
+
|
|
1235
|
+
#### 参数
|
|
1236
|
+
|
|
1237
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
1238
|
+
|--------|------|------|--------|------|
|
|
1239
|
+
| `refId` | string | ✅ | - | 元素引用 ID(必须是自定义组件) |
|
|
1240
|
+
| `method` | string | ✅ | - | 方法名 |
|
|
1241
|
+
| `args` | array | ⭐ | [] | 方法参数 |
|
|
1242
|
+
|
|
1243
|
+
#### 返回值
|
|
1244
|
+
|
|
1245
|
+
```typescript
|
|
1246
|
+
{
|
|
1247
|
+
success: true,
|
|
1248
|
+
message: "Element method \"refresh\" called successfully",
|
|
1249
|
+
result: { success: true }
|
|
1250
|
+
}
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
#### 使用示例
|
|
1254
|
+
|
|
1255
|
+
```javascript
|
|
1256
|
+
// 示例 1: 调用自定义组件方法
|
|
1257
|
+
const component = await page_query({
|
|
1258
|
+
selector: "custom-list",
|
|
1259
|
+
save: true
|
|
1260
|
+
})
|
|
1261
|
+
await element_call_method({
|
|
1262
|
+
refId: component.refId,
|
|
1263
|
+
method: "loadMore"
|
|
1264
|
+
})
|
|
1265
|
+
|
|
1266
|
+
// 示例 2: 带参数调用
|
|
1267
|
+
await element_call_method({
|
|
1268
|
+
refId: component.refId,
|
|
1269
|
+
method: "updateItem",
|
|
1270
|
+
args: [123, { name: "新名称" }]
|
|
1271
|
+
})
|
|
1272
|
+
```
|
|
1273
|
+
|
|
1274
|
+
---
|
|
1275
|
+
|
|
1276
|
+
## 完整示例:表单交互测试
|
|
1277
|
+
|
|
1278
|
+
```javascript
|
|
1279
|
+
// 场景:测试登录表单的完整交互流程
|
|
1280
|
+
async function testLoginForm() {
|
|
1281
|
+
try {
|
|
1282
|
+
// 1. 启动并导航到登录页
|
|
1283
|
+
await miniprogram_launch({ projectPath: "/path/to/project" })
|
|
1284
|
+
await miniprogram_navigate({
|
|
1285
|
+
method: "navigateTo",
|
|
1286
|
+
url: "/pages/login/login"
|
|
1287
|
+
})
|
|
1288
|
+
|
|
1289
|
+
// 2. 查询表单元素
|
|
1290
|
+
const username = await page_query({
|
|
1291
|
+
selector: "#username",
|
|
1292
|
+
save: true
|
|
1293
|
+
})
|
|
1294
|
+
const password = await page_query({
|
|
1295
|
+
selector: "#password",
|
|
1296
|
+
save: true
|
|
1297
|
+
})
|
|
1298
|
+
const submitBtn = await page_query({
|
|
1299
|
+
selector: ".submit-btn",
|
|
1300
|
+
save: true
|
|
1301
|
+
})
|
|
1302
|
+
|
|
1303
|
+
// 3. 填写表单
|
|
1304
|
+
await element_input({
|
|
1305
|
+
refId: username.refId,
|
|
1306
|
+
value: "testuser"
|
|
1307
|
+
})
|
|
1308
|
+
await element_input({
|
|
1309
|
+
refId: password.refId,
|
|
1310
|
+
value: "password123"
|
|
1311
|
+
})
|
|
1312
|
+
|
|
1313
|
+
// 4. 验证输入内容
|
|
1314
|
+
const usernameValue = await element_get_value({ refId: username.refId })
|
|
1315
|
+
console.log("✅ 用户名:", usernameValue.value)
|
|
1316
|
+
|
|
1317
|
+
// 5. 检查按钮状态
|
|
1318
|
+
const btnClass = await element_get_attribute({
|
|
1319
|
+
refId: submitBtn.refId,
|
|
1320
|
+
name: "class"
|
|
1321
|
+
})
|
|
1322
|
+
if (!btnClass.value.includes("disabled")) {
|
|
1323
|
+
console.log("✅ 提交按钮已启用")
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
// 6. 点击提交
|
|
1327
|
+
await element_tap({ refId: submitBtn.refId })
|
|
1328
|
+
|
|
1329
|
+
// 7. 等待并验证结果
|
|
1330
|
+
await page_wait_for({
|
|
1331
|
+
selector: ".success-toast",
|
|
1332
|
+
timeout: 3000
|
|
1333
|
+
})
|
|
1334
|
+
const toast = await page_query({
|
|
1335
|
+
selector: ".success-toast",
|
|
1336
|
+
save: true
|
|
1337
|
+
})
|
|
1338
|
+
const toastText = await element_get_text({ refId: toast.refId })
|
|
1339
|
+
console.log("✅ 登录成功:", toastText.text)
|
|
1340
|
+
|
|
1341
|
+
// 8. 截图
|
|
1342
|
+
await miniprogram_screenshot({
|
|
1343
|
+
filename: "login-success.png"
|
|
1344
|
+
})
|
|
1345
|
+
|
|
1346
|
+
console.log("✅ 表单测试完成")
|
|
1347
|
+
|
|
1348
|
+
} catch (error) {
|
|
1349
|
+
console.error("❌ 测试失败:", error.message)
|
|
1350
|
+
await miniprogram_screenshot({
|
|
1351
|
+
filename: "test-error.png"
|
|
1352
|
+
})
|
|
1353
|
+
throw error
|
|
1354
|
+
} finally {
|
|
1355
|
+
await miniprogram_close()
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
testLoginForm()
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
---
|
|
1363
|
+
|
|
1364
|
+
## 故障排除
|
|
1365
|
+
|
|
1366
|
+
### 问题 1: 元素引用失效
|
|
1367
|
+
|
|
1368
|
+
**错误**: `Element not found with refId: elem_xxx`
|
|
1369
|
+
|
|
1370
|
+
**解决方案**:
|
|
1371
|
+
1. 检查元素是否已被销毁(页面跳转、组件卸载)
|
|
1372
|
+
2. 使用 `page_query` 重新获取引用
|
|
1373
|
+
3. 确认 `save: true` 已设置
|
|
1374
|
+
|
|
1375
|
+
```javascript
|
|
1376
|
+
// ❌ 错误:页面跳转后引用失效
|
|
1377
|
+
const btn = await page_query({ selector: ".btn", save: true })
|
|
1378
|
+
await miniprogram_navigate({ method: "navigateTo", url: "/other" })
|
|
1379
|
+
await element_tap({ refId: btn.refId }) // 错误!
|
|
1380
|
+
|
|
1381
|
+
// ✅ 正确:跳转后重新查询
|
|
1382
|
+
await miniprogram_navigate({ method: "navigateTo", url: "/other" })
|
|
1383
|
+
const newBtn = await page_query({ selector: ".btn", save: true })
|
|
1384
|
+
await element_tap({ refId: newBtn.refId })
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1387
|
+
### 问题 2: 组件特定方法调用失败
|
|
1388
|
+
|
|
1389
|
+
**错误**: `Method not supported for this element type`
|
|
1390
|
+
|
|
1391
|
+
**解决方案**:
|
|
1392
|
+
确认元素类型与方法匹配:
|
|
1393
|
+
- `element_scroll_to` → `scroll-view`
|
|
1394
|
+
- `element_swipe_to` → `swiper`
|
|
1395
|
+
- `element_slide_to` → `slider`
|
|
1396
|
+
- `element_move_to` → `movable-view`
|
|
1397
|
+
|
|
1398
|
+
```javascript
|
|
1399
|
+
// 检查元素类型
|
|
1400
|
+
const tagName = await element_get_property({
|
|
1401
|
+
refId: el.refId,
|
|
1402
|
+
name: "tagName"
|
|
1403
|
+
})
|
|
1404
|
+
console.log("元素类型:", tagName.value)
|
|
1405
|
+
```
|
|
1406
|
+
|
|
1407
|
+
### 问题 3: 触摸事件不生效
|
|
1408
|
+
|
|
1409
|
+
**错误**: 触摸手势没有效果
|
|
1410
|
+
|
|
1411
|
+
**解决方案**:
|
|
1412
|
+
1. 确保 touchstart/move/end 正确配对
|
|
1413
|
+
2. 检查触摸点坐标是否在元素范围内
|
|
1414
|
+
3. 使用 `element_trigger` 作为替代
|
|
1415
|
+
|
|
1416
|
+
```javascript
|
|
1417
|
+
// ✅ 正确的触摸手势序列
|
|
1418
|
+
await element_touchstart({ refId, touches: [p0], changedTouches: [p0] })
|
|
1419
|
+
await element_touchmove({ refId, touches: [p1], changedTouches: [p1] })
|
|
1420
|
+
await element_touchend({ refId, touches: [], changedTouches: [p1] })
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
---
|
|
1424
|
+
|
|
1425
|
+
## 技术细节
|
|
1426
|
+
|
|
1427
|
+
### 元素引用生命周期
|
|
1428
|
+
|
|
1429
|
+
- **创建**: `page_query({ save: true })` 时创建
|
|
1430
|
+
- **存储**: 存储在 Session 的 `elements` Map 中
|
|
1431
|
+
- **失效**: 页面销毁、会话超时(30 分钟)、`miniprogram_close()`
|
|
1432
|
+
- **清理**: `miniprogram_disconnect()` 保留,`miniprogram_close()` 清除
|
|
1433
|
+
|
|
1434
|
+
### 坐标系统
|
|
1435
|
+
|
|
1436
|
+
- **物理像素**: 所有坐标和尺寸均为物理像素(px),非 rpx
|
|
1437
|
+
- **原点**: 页面左上角为 (0, 0)
|
|
1438
|
+
- **触摸坐标**: `pageX/pageY` 相对于页面,`clientX/clientY` 相对于视口
|
|
1439
|
+
|
|
1440
|
+
### 性能优化
|
|
1441
|
+
|
|
1442
|
+
- **批量操作**: 使用 `page_query_all` 一次获取多个元素
|
|
1443
|
+
- **引用缓存**: 使用 `save: true` 避免重复查询
|
|
1444
|
+
- **避免频繁截图**: 截图操作较慢,仅在必要时使用
|
|
1445
|
+
|
|
1446
|
+
---
|
|
1447
|
+
|
|
1448
|
+
**相关文档**:
|
|
1449
|
+
- [Page API](./page.md) - 页面级别操作
|
|
1450
|
+
- [Assert API](./assert.md) - 元素断言验证
|
|
1451
|
+
- [Snapshot API](./snapshot.md) - 元素快照捕获
|
|
1452
|
+
- [使用示例](../../examples/02-form-interaction.md) - 表单交互完整示例
|
|
1453
|
+
|
|
1454
|
+
**最后更新**: 2025-10-02
|