目录
- 摘要
- 1. 引言 - JavaScript 执行的价值
- 1.1 JS 执行应用场景
- 1.2 eval 功能概览
- 1.3 执行方式
- 2. 基本执行操作
- 2.1 执行简单脚本
- 2.2 获取页面信息
- 2.3 执行多行脚本
- 3. 数据获取
- 3.1 获取元素内容
- 3.2 获取表单数据
- 3.3 获取所有输入值
- 3.4 获取计算样式
- 4. DOM 操作
- 4.1 修改元素内容
- 4.2 修改元素HTML
- 4.3 添加元素
- 4.4 删除元素
- 4.5 修改属性
- 5. 样式控制
- 5.1 修改内联样式
- 5.2 添加/删除类
- 5.3 主题切换
- 6. 事件处理
- 6.1 触发点击
- 6.2 触发表单提交
- 6.3 触发自定义事件
- 7. 实战案例一:动态数据更新
- 7.1 场景描述
- 7.2 实现代码
- 7.3 更新图表
- 8. 实战案例二:表单自动填充
- 8.1 场景描述
- 8.2 实现代码
- 9. 实战案例三:内容提取
- 9.1 场景描述
- 9.2 实现代码
- 10. 高级技巧
- 10.1 异步操作
- 10.2 等待元素
- 10.3 批量操作
- 11. 安全注意事项
- 11.1 安全风险
- 11.2 安全实践
- 12. 总结
- 12.1 核心要点
- 12.2 最佳实践
- 12.3 下一步
- 参考资料
摘要
本文深入探讨 OpenClaw Canvas 的 JavaScript 执行功能。从基本执行、数据获取、DOM操作到高级应用,全面解析如何通过 eval 注入 JavaScript 实现灵活的界面控制。通过实际案例演示数据提取、动态更新、事件处理等场景,帮助开发者掌握 Canvas 的高级控制能力。⚡
1. 引言 - JavaScript 执行的价值
1.1 JS 执行应用场景
| 场景 | 说明 | 示例 |
|---|---|---|
| 数据获取 | 获取页面数据 | 读取表单值 |
| DOM操作 | 修改页面元素 | 更新内容 |
| 事件触发 | 触发页面事件 | 点击按钮 |
| 动态更新 | 实时更新内容 | 刷新数据 |
| 样式控制 | 动态修改样式 | 切换主题 |
1.2 eval 功能概览
1.3 执行方式
| 方式 | 说明 | 返回值 |
|---|---|---|
| 同步执行 | 立即执行并返回 | 有 |
| 异步执行 | 异步执行 | Promise |
2. 基本执行操作
2.1 执行简单脚本
result=canvas(action="eval",javaScript="1 + 1")# result = 22.2 获取页面信息
# 获取标题title=canvas(action="eval",javaScript="document.title")# 获取URLurl=canvas(action="eval",javaScript="window.location.href")# 获取HTMLhtml=canvas(action="eval",javaScript="document.documentElement.outerHTML")2.3 执行多行脚本
result=canvas(action="eval",javaScript=""" const title = document.title; const url = window.location.href; JSON.stringify({ title, url }); """)3. 数据获取
3.1 获取元素内容
defget_element_text(selector):"""获取元素文本"""returncanvas(action="eval",javaScript=f""" document.querySelector('{selector}').textContent """)# 使用示例text=get_element_text("#main-title")3.2 获取表单数据
defget_form_data(form_selector):"""获取表单数据"""returncanvas(action="eval",javaScript=f""" const form = document.querySelector('{form_selector}'); const formData = new FormData(form); const data = {{}}; for (let [key, value] of formData.entries()) {{ data[key] = value; }} JSON.stringify(data); """)3.3 获取所有输入值
defget_all_inputs():"""获取所有输入框的值"""returncanvas(action="eval",javaScript=""" const inputs = document.querySelectorAll('input, textarea, select'); const data = {}; inputs.forEach(input => { const name = input.name || input.id; if (name) { data[name] = input.value; } }); JSON.stringify(data); """)3.4 获取计算样式
defget_computed_style(selector,property):"""获取计算样式"""returncanvas(action="eval",javaScript=f""" const element = document.querySelector('{selector}'); window.getComputedStyle(element).getPropertyValue('{property}'); """)4. DOM 操作
4.1 修改元素内容
defset_element_text(selector,text):"""设置元素文本"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').textContent = '{text}'; """)4.2 修改元素HTML
defset_element_html(selector,html):"""设置元素HTML"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').innerHTML = `{html}`; """)4.3 添加元素
defappend_element(parent_selector,html):"""添加子元素"""canvas(action="eval",javaScript=f""" const parent = document.querySelector('{parent_selector}'); const div = document.createElement('div'); div.innerHTML = `{html}`; parent.appendChild(div.firstElementChild); """)4.4 删除元素
defremove_element(selector):"""删除元素"""canvas(action="eval",javaScript=f""" const element = document.querySelector('{selector}'); if (element) element.remove(); """)4.5 修改属性
defset_attribute(selector,attr,value):"""设置属性"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').setAttribute('{attr}', '{value}'); """)5. 样式控制
5.1 修改内联样式
defset_style(selector,property,value):"""设置样式"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').style.{property}= '{value}'; """)# 使用示例set_style('#header','backgroundColor','#667eea')set_style('#content','display','none')5.2 添加/删除类
defadd_class(selector,class_name):"""添加类"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').classList.add('{class_name}'); """)defremove_class(selector,class_name):"""删除类"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').classList.remove('{class_name}'); """)deftoggle_class(selector,class_name):"""切换类"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').classList.toggle('{class_name}'); """)5.3 主题切换
deftoggle_theme():"""切换主题"""canvas(action="eval",javaScript=""" document.body.classList.toggle('dark-theme'); """)6. 事件处理
6.1 触发点击
deftrigger_click(selector):"""触发点击事件"""canvas(action="eval",javaScript=f""" document.querySelector('{selector}').click(); """)6.2 触发表单提交
defsubmit_form(form_selector):"""提交表单"""canvas(action="eval",javaScript=f""" document.querySelector('{form_selector}').submit(); """)6.3 触发自定义事件
deftrigger_custom_event(selector,event_name,detail=None):"""触发自定义事件"""detail_json=json.dumps(detail)ifdetailelse'{}'canvas(action="eval",javaScript=f""" const event = new CustomEvent('{event_name}', {{ detail:{detail_json}}}); document.querySelector('{selector}').dispatchEvent(event); """)7. 实战案例一:动态数据更新
7.1 场景描述
实时更新 Canvas 中的数据展示。
7.2 实现代码
defupdate_dashboard(data):"""更新仪表盘数据"""# 构建更新脚本updates=[]forkey,valueindata.items():updates.append(f"document.getElementById('{key}').textContent = '{value}';")canvas(action="eval",javaScript="\n".join(updates))# 使用示例update_dashboard({"total-users":"1,234","active-users":"567","requests":"12,345","success-rate":"99.5%"})7.3 更新图表
defupdate_chart(chart_id,new_data):"""更新图表数据"""canvas(action="eval",javaScript=f""" const chart = Chart.getChart('{chart_id}'); if (chart) {{ chart.data.datasets[0].data ={json.dumps(new_data)}; chart.update(); }} """)8. 实战案例二:表单自动填充
8.1 场景描述
自动填充表单数据。
8.2 实现代码
deffill_form(data):"""填充表单"""fill_scripts=[]forfield,valueindata.items():script=f""" const field = document.querySelector('[name="{field}"], #{field}'); if (field) {{ if (field.type === 'checkbox' || field.type === 'radio') {{ field.checked ={str(value).lower()}; }} else if (field.tagName === 'SELECT') {{ field.value = '{value}'; }} else {{ field.value = '{value}'; }} }} """fill_scripts.append(script)canvas(action="eval",javaScript="\n".join(fill_scripts))# 使用示例fill_form({"username":"admin","email":"admin@example.com","role":"admin","active":True})9. 实战案例三:内容提取
9.1 场景描述
从 Canvas 中提取结构化数据。
9.2 实现代码
defextract_table_data(table_selector):"""提取表格数据"""returncanvas(action="eval",javaScript=f""" const table = document.querySelector('{table_selector}'); const rows = table.querySelectorAll('tr'); const data = []; rows.forEach(row => {{ const cells = row.querySelectorAll('td, th'); const rowData = []; cells.forEach(cell => rowData.push(cell.textContent.trim())); data.push(rowData); }}); JSON.stringify(data); """)defextract_list_data(list_selector):"""提取列表数据"""returncanvas(action="eval",javaScript=f""" const items = document.querySelectorAll('{list_selector}> li'); const data = []; items.forEach(item => {{ data.push(item.textContent.trim()); }}); JSON.stringify(data); """)10. 高级技巧
10.1 异步操作
defasync_operation():"""异步操作"""returncanvas(action="eval",javaScript=""" (async () => { const response = await fetch('/api/data'); const data = await response.json(); return JSON.stringify(data); })() """)10.2 等待元素
defwait_for_element(selector,timeout=5000):"""等待元素出现"""returncanvas(action="eval",javaScript=f""" (async () => {{ const start = Date.now(); while (Date.now() - start <{timeout}) {{ const element = document.querySelector('{selector}'); if (element) return true; await new Promise(r => setTimeout(r, 100)); }} return false; }})() """)10.3 批量操作
defbatch_dom_operations(operations):"""批量DOM操作"""scripts=[]foropinoperations:ifop['type']=='setText':scripts.append(f"document.querySelector('{op['selector']}').textContent = '{op['value']}';")elifop['type']=='setHtml':scripts.append(f"document.querySelector('{op['selector']}').innerHTML = `{op['value']}`;")elifop['type']=='click':scripts.append(f"document.querySelector('{op['selector']}').click();")canvas(action="eval",javaScript="\n".join(scripts))11. 安全注意事项
11.1 安全风险
| 风险 | 说明 | 防护措施 |
|---|---|---|
| XSS攻击 | 注入恶意脚本 | 转义用户输入 |
| 数据泄露 | 读取敏感数据 | 权限控制 |
| 无限循环 | 死循环脚本 | 超时限制 |
| DOM破坏 | 破坏页面结构 | 操作验证 |
11.2 安全实践
defsafe_eval(script,user_input):"""安全的执行"""# 转义用户输入escaped=user_input.replace("'","\\'").replace('"','\\"')# 使用参数化脚本safe_script=script.replace('{input}',escaped)returncanvas(action="eval",javaScript=safe_script)12. 总结
12.1 核心要点
| 要点 | 说明 |
|---|---|
| 数据获取 | 读取页面内容和数据 |
| DOM操作 | 修改元素和结构 |
| 样式控制 | 动态修改样式 |
| 事件触发 | 触发页面事件 |
12.2 最佳实践
- 转义用户输入
- 使用参数化脚本
- 添加错误处理
- 限制执行时间
12.3 下一步
- 第54篇:OpenClaw Canvas 截图:页面捕获与保存
- 第55篇:OpenClaw Canvas A2UI:交互式界面开发
参考资料
- OpenClaw 官方文档
- JavaScript DOM操作
- XSS防护