JSBox功能与语法全景笔记:从入门到进阶

# JSBox功能与语法全景笔记:从入门到进阶 在移动端的工具谱系里,JSBox像是一把折叠刀——小,却有分工细腻的刀锋;轻,却能在日常生活的细缝中解决实事。有人把它当作“脚本工具”,有人把它当作“低门槛的编程实验室”。而我更愿意把它看成一种“个人化的生产资料”:以JavaScript为骨架,以一组贴合移动情境的API为肌理,去缝合那些散落在各个App与服务之间的碎片流程。下面这份“全景笔记”,既是功能与语法的速查,也是方法与思路的地图。愿它与每一个爱折腾的你相遇,像一支在掌心旋出的光。 一、整体认知:JSBox能做什么 - 以JavaScript为语言内核,提供移动端可直接运行的脚本环境。 - 封装了大量系统与常用场景API:UI界面、网络请求、文件读写、剪贴板、通知、分享、媒体处理、数据库等。 - 支持可视化界面构建(原生风格UI),并能以“分享扩展/快捷指令/URL Scheme”与系统和其他应用联动。 - 支持模块化、异步编程与一定程度的原生桥接($objc),能满足从“小工具”到“中型工作流”的构建需求。 注:JSBox版本会演进,具体API以你当前版本的文档为准。本文以常见、稳定的接口为主,示例尽量采用通行写法。 二、语法基座:JavaScript的那些要点 JSBox的语法基础是现代JavaScript。你可放心使用: - 变量与作用域:let、const优先(避免var) - 模块化:支持CommonJS风格的require/exports/module.exports - 异步编程:Promise、async/await - 结构化数据:JSON.parse/JSON.stringify - 常见内置对象与方法:Array.map/filter/reduce、String.replace、RegExp等 简例:模块化 // 文件:utils.js function slugify(s) { return s.toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]/g, ""); } module.exports = { slugify }; // 文件:main.js const { slugify } = require("./utils"); $console.info(slugify("Hello JSBox!")); 三、脚本与项目结构:如何组织你的“刀锋” - 单文件脚本:适合极简工具,快速试验。 - 多文件模块化:把通用逻辑拆到utils、services等,主脚本负责流程编排。 - 沙盒文件系统:相对路径即可读写;可将资源放入项目目录中统一管理。 - 执行环境:既可在App内运行,也可作为分享扩展、快捷指令动作或通过URL Scheme触发。根据环境差异使用$context与$app.env判断。 四、核心UI体系:$ui与视图布局 $ui是JSBox最具辨识度的能力之一,它让你以简洁描述构建接近原生风格的界面。 1) 最小界面 $ui.render({ props: { title: "我的小工具" }, views: [{ type: "label", props: { text: "你好,JSBox", align: $align.center, font: $font(18) }, layout: (make, view) => { make.center.equalTo(view.super); }, events: { tapped: () => $ui.toast("被点了一下") } }] }); 2) 常用视图类型 - label、button、image、input、text、list、matrix、tab、web、markdown、canvas、video、progress、switch、slider、stepper等。 - 每个视图都具备props(属性)、layout(自动布局)、events(事件)三要素。 3) 自动布局与属性辅助 - 布局函数layout采用“约束式”写法(类似Masonry/SnapKit): make.left.right.inset(12); make.top.equalTo(20); make.height.equalTo(44); - 常用辅助常量:$align、$color、$font等。 - 动画:$ui.animate(async () => { /* 修改属性 */ }); 4) 页面栈与弹窗 - $ui.push({...}) / $ui.pop():页面入栈/出栈。 - $ui.alert("提示信息") 或 $ui.alert({title, message, actions})。 - $ui.menu(["A","B","C"]).then(({index, title}) => {}); - $ui.toast("已完成"); $ui.loading(true/false)。 五、网络与数据:$http $http封装了HTTP请求的常见模式,支持异步与文件传输。 1) GET与POST const resp = await $http.get({ url: "https://api.example.com/posts", header: { "Accept": "application/json" }, timeout: 10 }); if (resp.error) { $ui.error("网络异常"); } else { const items = resp.data; // 自动JSON解析(Content-Type正确时) $console.log(items.length); } await $http.post({ url: "https://api.example.com/login", header: { "Content-Type": "application/json" }, body: { user: "tom", pass: "123456" } }); 2) 下载与上传 await $http.download({ url: "https://example.com/image.jpg", showsProgress: true, handler: (resp) => { if (resp.data) $file.write({ data: resp.data, path: "image.jpg" }); } }); await $http.upload({ url: "https://example.com/upload", files: [{ data: $file.read("image.jpg"), name: "file", filename: "image.jpg" }] }); 3) 细节与技巧 - 超时timeout、重试策略(自建逻辑)、并发控制(Promise.allSettled)。 - Cookie/会话:自行管理header或使用$cache存取令牌。 - 错误处理:resp.error与状态码分支。 六、文件系统:$file与$data $file是你的沙盒工具箱,读写、移动、拷贝、删除一应俱全。 - 判断与列目录 if ($file.exists("docs")) { const files = $file.list("docs"); // 返回文件名数组 $console.log(files); } else { $file.mkdir("docs"); } - 读写文本与二进制 $file.write({ path: "docs/hello.txt", string: "你好,世界" }); const content = $file.read("docs/hello.txt").string; const bin = $file.read("image.jpg"); // 数据对象 $file.write({ path: "copy.jpg", data: bin }); - 移动/复制/删除 $file.move({ src: "a.txt", dst: "b.txt" }); $file.copy({ src: "b.txt", dst: "backup/b.txt" }); $file.delete("backup/b.txt"); - $data辅助 const buf = $data({ string: JSON.stringify({ a: 1 }) }); $file.write({ path: "data.json", data: buf }); 七、剪贴板、输入、通知与分享:$clipboard / $input / $notification / $share - 剪贴板 const text = $clipboard.text; $clipboard.text = (text || "").trim(); const img = $clipboard.image; // 亦可读写图片 - 输入对话 const name = await $input.text({ placeholder: "请输入名称" }); const picked = await $input.select(["A", "B", "C"]); // 返回所选项 const date = await $input.date(); // 返回JS日期对象 - 通知 await $notification.schedule({ title: "提醒", body: "喝水了", date: new Date(Date.now() + 10 * 60 * 1000) // 十分钟后 }); - 分享 $share.sheet(["标题", "要分享的文本"]); $share.sheet($file.read("image.jpg")); // 分享图片或数据 八、媒体与图像:$photo / $qrcode / $quicklook - 选图/拍照 const result = await $photo.pick({ count: 3 }); if (result && result.results) { for (const it of result.results) { $file.write({ path: `picked/${Date.now()}.jpg`, data: it.data }); } } - 二维码 const img = $qrcode.encode("https://example.com"); $quicklook.open({ image: img }); - 预览 $quicklook.open("docs/hello.txt"); $quicklook.open({ data: $file.read("image.jpg") }); 九、文本与编码:$text与$detector $text提供多种常用编码与散列方法,$detector用于从文本中识别结构化片段。 - 编解码与散列 const s = "你好 世界!"; $console.log($text.URLEncode(s)); $console.log($text.URLDecode($text.URLEncode(s))); $console.log($text.base64Encode("JSBox")); $console.log($text.base64Decode("SlNCb3g=")); $console.log($text.MD5("abc123")); - 检测器 const links = $detector.link("站点:https://example.com 与 http://a.cn"); $console.log(links); // 返回匹配到的链接集合 十、缓存、偏好与数据库:$cache / $prefs / $sqlite - 缓存(进程内/本地缓存) $cache.set("token", "abcdef"); const token = $cache.get("token"); $cache.remove("token"); - 偏好(如可用) $prefs.set("theme", "dark"); $console.log($prefs.get("theme")); - SQLite(如版本支持) const db = $sqlite.open("data.db"); db.update("CREATE TABLE IF NOT EXISTS notes(id INTEGER PRIMARY KEY, title TEXT)"); db.update("INSERT INTO notes(title) VALUES(?)", ["第一条"]); const rows = db.query("SELECT * FROM notes"); $console.log(rows); db.close(); 十一、设备与系统:$device / $app / $safari - 设备信息与反馈 $console.log($device.name); $console.log($device.model); $console.log($device.systemVersion); $device.taptic(); // 轻触反馈(如设备支持) $device.brightness = 0.8; - 环境判断与URL $console.log($app.env); // "app" | "extension" | "keyboard" 等 $app.openURL("https://example.com"); // 系统浏览器或内嵌 $safari.open("https://example.com"); // 使用Safari视图(如可用) - 应用生命周期 $ui.toast("Hello"); $delay(1, () => $ui.toast("1秒后")); // 亦可用$timer实现 十二、定时、线程与并发:$timer / $thread - 定时器 const timer = $timer.schedule({ interval: 2, // 秒 handler: () => $console.log("tick") }); // 需要时停止 timer.invalidate(); - 线程与切换 $thread.background({ handler: () => { const sum = Array.from({ length: 1e5 }, (_, i) => i).reduce((a, b) => a + b, 0); $thread.main({ handler: () => $ui.toast("计算完成 " + sum) }); } }); 十三、上下文输入与扩展场景:$context 当脚本作为“分享扩展”或“URL Scheme”被调用时,输入常由$context提供。 - 分享扩展常见入口 if ($context.text) { $console.log("来自分享的文本:", $context.text); } if ($context.image) { $file.write({ path: "shared.jpg", data: $context.image }); } if ($context.data) { $file.write({ path: "raw.bin", data: $context.data }); } - URL Scheme参数(示例) /* 假设通过:jsbox://run?name=MyScript&query=hello 你可通过 $context.query 获取 */ $console.log($context.query); // "hello" - 与快捷指令联动 在捷径里调用脚本时,输入也可通过$context.*传入;脚本完成后可用$clipboard / $share / $quicklook输出结果,或写入文件再交回捷径处理。 十四、网络环境与状态:$network / $location(如可用) - 网络状态 $console.log($network.wifi.ssid); $console.log($network.ip); - 定位(权限申请后) $location.startUpdates({ handler: loc => { $console.log(loc.latitude, loc.longitude); $location.stopUpdates(); } }); 十五、进阶桥接:$objc(谨慎使用) 当现有API不能满足需求时,$objc允许你以桥接方式触达部分原生能力。它像是一扇“动力门”,但也意味着你要承担更多版本与兼容性风险。 示例:获取系统版本 const device = $objc("UIDevice").$currentDevice(); const version = device.$systemVersion().rawValue(); $console.log("iOS:", version); 示例:使用原生视图(示意) const btn = $objc("UIButton").$new(); btn.$setTitle_forState($("NSString").$stringWithString("点我"), 0); const ocview = btn; // 在$ui里托管需更多桥接代码,此处仅示意 说明:$objc调用以$前缀映射Objective-C选择器,原生对象到JS值需rawValue取值。桥接细节庞杂,建议优先使用JSBox封装API。 十六、典型小工具范式:从“输入-处理-输出”出发 - 文本清洗器 async function cleanClipboard() { let s = ($clipboard.text || "").replace(/\s+\n/g, "\n").replace(/\t/g, " "); s = s.replace(/[ ]+/g, " "); // 清除不间断空格 $clipboard.text = s.trim(); $ui.toast("已清洗并复制"); } cleanClipboard(); - 图片批量压缩与重命名 async function batchImage() { const picked = await $photo.pick({ count: 9 }); if (!picked || !picked.results) return; let i = 1; for (const it of picked.results) { const name = `IMG_${Date.now()}_${i++}.jpg`; // 直接写入;如需压缩可借助$ui/canvas或图像API(视版本) $file.write({ path: `out/${name}`, data: it.data }); } $ui.toast("已保存到 out/"); } batchImage(); - REST API拉取与Markdown汇总 async function fetchAndReport() { const resp = await $http.get("https://api.example.com/report"); if (resp.error) return $ui.error("拉取失败"); const list = resp.data.items || []; const md = ["# 每日简报", ""].concat(list.map((x, i) => `${i + 1}. ${x.title}`)).join("\n"); $file.write({ path: "report.md", string: md }); $quicklook.open("report.md"); } fetchAndReport(); 十七、错误处理与健壮性:给工具“打磨棱角” - 统一错误捕获:在每个await可能失败的点加try/catch;在UI入口处加兜底提示。 - 超时与重试:网络调用设定timeout,失败后指数退避重试。 - 资源清理:定时器、线程、临时文件按生命周期清理。 - 用户反馈:关键路径toast/alert,不打扰又不失联。 示例:带重试的GET async function getWithRetry(url, times = 3, delay = 500) { for (let i = 0; i < times; i++) { const resp = await $http.get({ url, timeout: 8 }); if (!resp.error && resp.statusCode === 200) return resp.data; await new Promise(r => setTimeout(r, delay * (i + 1))); } throw new Error("网络不稳定,请稍后重试"); } 十八、性能与体验:让小工具“跑得轻盈” - 避免阻塞UI线程:重计算交给$thread.background。 - 按需加载:模块分拆、懒初始化。 - 数据持久:配置用$prefs/$cache,数据用$file/$sqlite。 - 可观察性:日志$console.log + 临界点$ui.toast,必要时落地日志文件。 十九、与系统/他应工具的边界:取与舍 - iOS沙盒、安全策略、后台限制,是任何“自动化梦想”必须尊重的地基。 - 在边界内做最顺滑的闭环:把“重复”交给脚本,把“判断”交给人。 - 与快捷指令结合:无代码的拼装 + 轻代码的弹性 = 成本最优的微自动化。 二十、速查(精选常用API清单) - UI:$ui.render / push / pop / alert / menu / toast / loading / animate - 视图:label / button / list / matrix / input / text / image / web / markdown / progress / switch / slider / stepper - 网络:$http.get / post / request / download / upload - 文件:$file.exists / list / mkdir / read / write / copy / move / delete - 数据:$data({string|path}) / JSON.parse / stringify - 剪贴板:$clipboard.text / image - 输入:$input.text / select / date - 预览:$quicklook.open - 分享:$share.sheet - 通知:$notification.schedule - 图像:$photo.pick / $qrcode.encode - 文本:$text.MD5 / SHA1 / base64Encode / base64Decode / URLEncode / URLDecode - 检测:$detector.link / email / phone - 设备:$device.name / model / systemVersion / taptic / brightness - 应用:$app.env / openURL - 定时:$timer.schedule - 线程:$thread.background / main - 上下文:$context.text / image / data / query - 数据库:$sqlite.open / query / update / close(如版本支持) - Safari:$safari.open(如版本支持) 二十一、学习路径与方法论:从“微痛点”开始 - 定一个“只要5分钟”的问题:比如“清洗剪贴板的文本并保存到笔记”。 - 用“输入-处理-输出”画出三块:对应$context/$clipboard → JavaScript处理 → $file/$share。 - 写出来,跑一遍;再把可复用的部分抽到utils;稍微加一点错误处理。 - 把它塞进你的路径:绑定到分享面板/快捷指令/主界面;让工具贴身随行。 - 去社区看看类似脚本,借鉴拆解与命名方式;不断做微小的迭代。 尾声:把“可编排”交还给个体 余秋雨说,文明常藏于细节。对今天的个体而言,细节是被一条条应用边界切得稀碎的时间、注意力与数据流。JSBox没有喧哗的声音,却在缝隙里把主动权交还给你:你可以亲手编排自己的微流程,给日常的重复动作安上一段可靠的机械臂。吴晓波常谈产业的“结构性效率”,而JSBox恰恰提供了个人层面的“结构性效率”:它不要求你成为工程师,却允许你像工程师一样思考与组织。 何为“功能语法大全”?不是把所有API流水账地堆成一面墙,而是给出一副可以反复参照的地图:知道去哪里查、知道用什么拼、知道边界在哪、知道如何让一个小工具稳稳地活下去。愿这份笔记成为你口袋里的一张折角纸:遇事一看、有用即抄、久而久之,刀锋在你的掌心里,越磨越亮。