用sketch-data-faker插件为设计稿批量填充Faker.js假数据

发布时间:2026/10/18 7:23:48
用sketch-data-faker插件为设计稿批量填充Faker.js假数据 简介面向 Sketch 设计师和前端开发者的数据填充插件基于 Faker.js 构建可在设计稿中快速生成姓名、邮箱、电话、段落等一百三十多种智能占位符内容。它支持在符号内部以及导入的 Sketch Libraries 中反复刷新出同一类型的不同随机数据适合为列表、表格或表单提供具有真实感的模拟信息解决设计阶段 Mock 数据重复枯燥的问题。资源包为 zip 压缩包大小约 919KB共 17 个文件以 JavaScript 脚本、JSON 配置、PNG 图标、XML 及 Markdown 文档为主其中脚本与配置分别承担插件逻辑和数据类型定义结构紧凑便于阅读或二次开发。目前已有 159 人学习浏览适合对 Sketch 插件机制、Faker.js 应用或前端 Mock 方案感兴趣的读者。借助这份资源可以完整了解插件清单的编写、随机内容的生成调用、图层插入与刷新机制并能参考其源码扩展自定义占位类型相关实现思路还可迁移到其他设计工具的数据模拟流程中。1. 给设计稿批量喂假数据sketch-data-faker 解决的是交付前最后一公里做了几年设计稿对接你会发现最耗时间的不是画界面而是给界面填内容。列表要 20 条用户信息、卡片要 8 个商品、设置页要 12 组账号数据手打既不真实又慢复制粘贴又容易穿帮。sketch-data-faker 这个 Sketch 插件核心就是做这件事它把 Faker.js 的 130 多种数据类型搬进 Sketch你在文本图层里写一个占位符它就能帮你生成对应类型的假数据再批量写回图层。适合三类人独立做作品集的设计师、需要给开发同学提供真实感样式的 UI 设计师、以及频繁做数据可视化 Demo 的开发者。它的学习成本几乎为零不需要写代码也能用但理解它的数据映射原理后你能把它改造成团队自己的数据生成工具。2. 130 种占位符的幕后组织数据映射、Faker.js 模板与文本识别原理2.1 占位符语法为什么是双花括号加命名空间用这个插件之前先理解它的核心约定你在文本图层里写的内容一旦包含{{name.firstName}}这种双花括号片段就会在运行填充命令时被替换成具体数据。双花括号不是随手定的它有两个原因。其一设计稿正文里单花括号太常见比如{价格}、{数量}双花括号能显著降低误触发的概率。其二name.firstName这种命名空间写法直接对应 Faker.js 内部的调用路径name是分类firstName是该分类下的具体方法两者用点连接语义直观到不需要查文档。Faker.js 本身是一个 Node 生态里非常成熟的假数据生成库它内部维护了一张巨大的模板表。{{name.firstName}}会被解析成一次faker.name.firstName()的函数调用{{internet.email}}则对应faker.internet.email()。sketch-data-faker 并没有重新发明一套数据生成逻辑它做的事情是把这张模板表搬运到了 Sketch 插件能访问到的 JavaScript 环境里同时补了一批 Faker.js 里没有的数据类型比如车牌号、颜色名、企业部门名称。所以标题里说来自 Faker.js 和其他来源其他来源指的就是这批额外注册的类型。2.2 数据表结构和命中过程整个插件的核心数据表拆开看就是一个普通的 JavaScript 对象。我用简化代码说明它的组织方式// data.js —— 类型注册表的简化结构示意 const registry { person: [ { label: First Name, template: {{name.firstName}} }, { label: Full Name, template: {{name.findName}} } ], internet: [ { label: Email, template: {{internet.email}} }, { label: Avatar, template: {{internet.avatar}} } ], custom: [ { label: License Plate, template: {{vehicle.vin}} } ] }; function matchTemplate(text) { // 提取所有双花括号片段 const pattern /\{\{([^{}])\}\}/g; const matches []; let m; while ((m pattern.exec(text)) ! null) { matches.push(m[1]); } return matches; }这段代码里registry按分类组织每个分类下是一组label和template的配对。matchTemplate是识别逻辑遍历文本图层里的字符串用正则把所有双花括号内的内容提取出来。注意我用了[^{}]而不是.*?这是有意的前者不允许嵌套花括号能避免把{{a}} {{b}}这种连续占位符错误吞并。当你在 Sketch 里选中一个写着{{name.findName}} 的邮件是 {{internet.email}}的文本图层并运行填充时插件先把这段文字拆成模板片段逐段交给 Faker.js 生成再拼回完整字符串。这个过程的顺序敏感点在于必须在一次生成周期内完成所有替换否则两次调用产生的随机数据会互相矛盾——比如姓名和邮箱对不上。实际代码中会用一次性faker.fake(template)调用而不是逐个替换。2.3 文本图层的读取与判定边界占位符写在哪、怎么被读出来决定了这个插件好不好用。Sketch 的文本图层在插件 API 里是一个Text对象它有text属性可以拿到字符串内容。但有一个隐蔽的坑当文本带着富文本样式时text属性返回的可能是去掉了样式的纯文本也可能带一些控制字符。我通常建议在填充前先对文本做一次String(layer.text)强转再 trim 掉首尾空白否则正则匹配很容易因为换行符而漏掉最后一个占位符。还有一个边界条件需要明确这个插件只处理文本图层不处理形状里的文本路径、不处理符号实例内部的文本。如果你选中的是一个 Group插件不会自动钻进去这一点到第 4 章避坑部分会展开讲。识别命中后插件会把原始文本保存到内存变量里等所有图层都生成完毕后统一写回这样保证一个画板内多次填充的数据风格一致。3. 跑通一次批量填充SketchJavaScript 调用链、菜单声明与图层写入3.1 插件包结构与 manifest 声明Sketch 插件本质上是一个带固定目录结构的文件夹最核心的是manifest.json和脚本文件。你下载的 zip 解压后目录里一定有Contents/Sketch/manifest.json这个文件决定了插件在 Sketch 菜单里长什么样、快捷键是什么、命令入口在哪里。一个最小可用的 manifest 是这样{ identifier: com.example.data-faker, name: Data Faker, description: Generate mock data from Faker.js, author: your-name, version: 1.0.0, commands: [ { name: Fill Selected Layers, identifier: data-faker.fill, script: plugin.js, handler: onFill, shortcut: ctrl cmd f } ], menu: { title: Data Faker, items: [data-faker.fill] } }这里的identifier是全局唯一标识建议用反向域名风格避免冲突。commands数组里每一项对应一个菜单动作script指向插件目录下的脚本文件handler是脚本文件里导出的函数名shortcut是快捷键声明。需要注意快捷键是字符串形式ctrl cmd f表示同时按 Control、Command、F 三个键如果声明格式写错Sketch 会静默忽略不会报错这也是后面避坑章节要提到的点。安装插件时Sketch 会把整个插件文件夹复制到~/Library/Application Support/com.bohemiansketch.bohemiancoding.plugins或新版本的 Plugins 目录下。检测安装是否成功的标志是 Sketch 顶部菜单栏出现 Plugins → Data Faker 子菜单。如果没出现优先检查 manifest 的 JSON 格式用系统自带的文本编辑器打开看一眼括号配平即可这个文件对格式极其敏感。3.2 从选中图层到写回文本的完整调用链第一次跑通批量填充重点看两段逻辑拿选中图层以及写回内容。Sketch 的 JavaScript API 提供了sketch.getSelectedLayers()函数返回当前选中图层数组但这个函数有兼容性问题老插件更常用的方式是直接从context.selection读取原生选中对象。我一般两者结合写一个通用的遍历函数// plugin.js —— 批量填充主流程 import sketch from sketch; export function onFill(context) { const doc sketch.getSelectedDocument(); const selection doc.selectedLayers; // 收集选中的文本图层 const textLayers []; selection.layers.forEach(layer { if (layer.type Text) { textLayers.push(layer); } else if (layer.type Group) { // 递归查找组内文本图层 collectTextLayers(layer, textLayers); } }); if (textLayers.length 0) { sketch.UI.message(No text layers selected.); return; } // 逐个图层替换占位符 textLayers.forEach(layer { const raw String(layer.text || ); const filled replacePlaceholders(raw); layer.text filled; }); sketch.UI.message(Filled ${textLayers.length} layers.); } function collectTextLayers(group, result) { group.layers.forEach(layer { if (layer.type Text) { result.push(layer); } else if (layer.type Group) { collectTextLayers(layer, result); } }); }doc.selectedLayers.layers是 Sketch API 提供的高层对象集合每个元素都有type属性和text属性读和写都走同一个属性这比原生 API 直观。sketch.UI.message会在画布底部弹一条淡入淡出的提示用于反馈填充数量干设计活的人不希望在填充完后再弹干扰性模态框所以这里特意选了 message 而不是 alert。replacePlaceholders函数内部做的事情就是第 2 章的 matchTemplate 加 faker 调用这里不再重复。写回时有一个参数细节直接给layer.text赋值Sketch 会保留图层原有的字号、颜色、对齐方式只替换字符串部分。这是很多人忽略的舒适点——它不会重置你的样式。3.3 数据源类型如何弹出给用户选择上面代码默认对占位符做全量替换但实际使用中你往往希望先选一个类型比如这次只填人名或这次只填邮箱。插件运行时应该弹一个下拉面板。常见做法是调用 Sketch 的 UI 框架import sketch from sketch; export function onFillWithPicker(context) { const selection sketch.getSelectedDocument().selectedLayers; const templates buildTemplateOptions(); // 从 registry 里拍平所有候选 const options templates.map(t t.label); const chosenIndex sketch.UI.getSelectionFromData( Select data type, options ); if (chosenIndex -1) return; const chosen templates[chosenIndex]; selection.layers.forEach(layer { if (layer.type Text) { layer.text chosen.template; // 直接把整个文本替换成一种数据 } }); }sketch.UI.getSelectionFromData是原生面板函数第一个参数是标题第二个是字符串数组返回用户选中的索引。这里有个分叉设计如果是带占位符的既有文本走 replace 逻辑如果是空文本图层就可以用chosen.template直接整体生成内容。实际插件两者的处理都有我在本地复现时更常用后者——先画一排文本图层全选然后按类型统一填充速度快得多。参数chosenIndex -1表示用户点了取消这个判断必须写否则undefined会触发后续数组越界。4. 高频问题排查与避坑中文数据、整组替换失灵和快捷键失效4.1 填充后富文本样式丢失只剩纯文本现象文本图层原本是局部标红、局部加粗的富文本运行填充后样式全部丢失变成纯黑色。 原因写回时用了非属性字符串赋值。部分封装在调用layer.setText()时传入的是普通字符串Sketch 会用默认样式重建整个 attributed string原生文本样式就散了。 解决写回前先读取原图层样式对象。合理做法是取出layer.sketchObject.attributedStringValue()只替换其中的可变部分或者干脆先备份layer.style赋值后再 restore。4.2 快捷键没反应菜单里也找不到现象manifest 里声明了shortcut: ctrl cmd f重启 Sketch 后按三键组合没有响应但是通过菜单手动点击可以填充。 原因快捷键格式不合规或与系统快捷键冲突。Sketch 对快捷键大小写敏感ctrl cmd F和ctrl cmd f是不同键另外如果系统里已经占用这个组合Sketch 不会弹冲突提示而是悄悄放弃自己那份。 解决把快捷键改成少用的组合比如shift cmd d然后完全退出 Sketch 重新打开。注意修改 manifest 后必须重启 Sketch插件系统不会热加载 manifest 变更。如果还不行打开系统设置里的键盘快捷键面板搜索相同组合排查冲突源。4.3 选中一个 Group 后填充无效果现象在画布上选中一个包含多个文本图层的组运行填充提示 Filled 0 layers。 原因doc.selectedLayers.layers返回的是第一层子对象如果一个组被整体选中这个 API 返回的可能是 Group 本身而不是组内的文本图层需要手动展开递归。 解决回到第 3 章那段代码collectTextLayers递归进入每个 Group。更好的习惯是先用 Sketch 的 Ungroup 快捷键把画板内的组拆平或者自动遍历group.layers深度优先。我在实际项目里把这段递归封装成了工具函数每次运行数据填充前都强制跑一遍杜绝漏填。4.4 生成的假数据全是英文想要中文人名和中文地址现象跑完填充后文本是 John Smith、123 Main Street设计稿是中文界面数据风格完全对不上。 原因Faker.js 的默认 locale 是英文sketch-data-faker 保留了这一默认值没有自动切换语言环境。 解决在插件初始化时设置faker.locale zh_CN这会切换人名、地址、电话等大部分分类。但注意 Faker.js 的中文语言包覆盖不全部分分类如vehicle和commerce仍会回退到英文。遇到这种情况不要硬改源码而是用第 5 章的自定义数据源方案补充。填完后人工抽检几条中文界面就不要混入英文产品名这一条我踩过不止一次。4.5 占位符没有被识别双花括号原样留在画布里现象文本图层写的{{name.firstName}}填充后画布上还是一模一样的字符串没有任何变化。 原因文本里可能带了不可见控制字符或者layer.text读取时返回的是NSAttributedString强转 String 后混入了\u{2028}之类的换行分隔符正则\s默认匹配不上这些分隔符。 解决匹配正则从/\{\{([^{}])\}\}/g改成/\{\{([\s\S]?)\}\}/g让任意字符包括换行都能被捕获。同时填充前用.replace(/\u2028/g, )把特殊分隔符统一替换成普通空格再执行替换逻辑。5. 把插件扩展成自己的数据源JSON 注入与自定义类型注册5.1 为什么 130 种类型还不够第 2 章的 registry 表是通用数据覆盖人名、地址、公司、互联网、金融、日期等通用场景但设计稿里最真实的假数据往往来自业务本身某个内容的标题风格、内部测试账号格式、行业术语组合。Faker.js 再强大也生成不了你们产品特有的分类名。所以合格的做法不是改源码而是给插件预留一个可加载的 JSON 数据文件让团队每个人都能往里加内容而不用碰核心逻辑。我一般会在插件目录下建一个custom-data.json结构是分类名到模板数组的映射。加载逻辑放在插件启动时用 Node 的文件读取接口把它并进主 registry。这样既保留了 Faker.js 的随机性又塞进了业务数据源。5.2 JSON 数据文件怎么写{ business: [ { label: Project Name, template: {{custom.projectName}} }, { label: Ticket Number, template: {{custom.ticketNo}} } ], test: [ { label: Test Account, template: {{custom.testAccount}} } ] }label是弹窗里显示给用户看的友好名称template是替换占位符。注意我把命名空间统一写成了custom.xxx这是刻意避开了person、internet等原生分类避免团队同学误以为这些是 Faker.js 内置函数。JSON 文件里不能写注释所以字段含义要在外层说明文档里讲清楚或者用label字段写足够自解释的中文名。5.3 自定义数据如何注册进 faker.js拿到 JSON 里的 template 字符串后要让它真正参与生成需要把这批自定义数据注册到 Faker.js 的 fake 调用链里。faker.js 是黑匣子但它的扩展机制是公开的可以往faker.custom命名空间挂函数。我推荐的做法是直接从 JSON 生成一组函数注入// custom-loader.js —— 从 JSON 文件注入自定义数据 const fs require(skpm/fs); const faker require(faker); function loadCustomData(filePath) { const raw fs.readFileSync(filePath, utf8); const data JSON.parse(raw); // 为每个模板注册一个生成函数 faker.custom faker.custom || {}; Object.keys(data).forEach(category { data[category].forEach(item { const key item.template.match(/custom\.(\w)/)[1]; faker.custom[key] () generateFromTemplate(item.template); }); }); } function generateFromTemplate(template) { // 逐个处理 template 里的字段 return template.replace(/\{\{(\w\.\w)\}\}/g, (match, path) { const [namespace, method] path.split(.); if (namespace custom faker.custom[method]) { return faker.custom[method](); } return faker.fake(match); }); }fs.readFileSync是 SKPM 提供的增强版文件接口可以访问插件包内相对路径。Openfaker.custom对象的过程就是在运行时注册函数。generateFromTemplate是关键它遍历模板里的每个占位符命中custom.前缀就调用注册函数否则回退给faker.fake原生处理。这种兜底设计让自定义模板里可以混用{{custom.projectName}}和{{name.firstName}}生成某项目负责人张三这类混合句子。加载完 JSON 后要同步更新弹窗候选列表。常见做法是把custom-data.json的分类数组 push 进 registry然后重新 build 一次模板选项数组。这个操作在插件每次运行时执行即可数据量通常很小内存代价可以忽略。注意 JSON 文件一旦格式错误JSON.parse会直接 throw插件运行会静默失败所以加载代码要包一层 try-catch失败时降级为纯 Faker.js 模式并提示用户检查 JSON 格式。5.4 一个内存缓存的小优化每次都readFileSync读取 JSON 不划算尤其是大团队维护的 data 文件动辄几百条模板。我习惯在插件模块顶层缓存数据对象只在文件变更时重新加载let customDataCache null; function getCustomData() { if (customDataCache) return customDataCache; customDataCache loadCustomData(custom-data.json); return customDataCache; }缓存必须放在模块作用域而不是函数内部否则每次调用都失效。缓解记忆压力的是插件每次运行是独立进程缓存生命周期等于一次填充命令的完整生命周期够用且不过度。如果团队数据文件更新频繁可以在弹窗里加一个 Reload Custom Data 菜单项手动清掉缓存重读这样既保证性能又给了后悔药。6. 验证一次假数据是否真的到位双跑对比与图层标记法填充完数据后最怕的就是看起来填了实际没填对。我吃过亏某次交付前没验证结果画布里一半文本框还是双花括号原样开发同学拿到的设计稿根本无法用于切图。从那以后我每次填充数据都强制走一遍双跑对比。双跑对比做法很简单第一次填充前先用 Faker.js 的随机种子机制固定随机流faker.seed(20240101)填完所有图层第二次把同样的占位符复制到另一组文本图层再次以同一 seed 填充。两次生成的文本应该完全一致。如果第二次出现了不同内容说明填充链里有非确定性逻辑比如某些类型走了系统随机而没走 faker 的随机流这就要回到第 2 章的匹配逻辑排查。图层标记法更直观。我习惯在填充命令执行前把占位符同时写进文本内容和一个独立图层名里。例如图层名叫>function verifyNoPlaceholders(layers) { const remaining layers.filter(layer { return /\{\{[\s\S]\}\}/.test(String(layer.text || )); }); if (remaining.length 0) { sketch.UI.message(Warning: ${remaining.length} layers still contain placeholders.); } return remaining.length 0; }这段代码在填充命令尾部调用一次把仍有占位符的图层数弹出来。别小看这一行校验它把填充是否成功从目测变成了可断言的状态。从那以后我每次批量填充都把这个校验挂在命令末尾就像写代码跑单测一样先让机器告诉我哪里没填上再谈视觉检查。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询