Snippet 参数输入修复总结
问题描述
用户反馈在使用代码片段(snippet)创建 widget 时,无法传递参数:
- 输入
stWidget、viewmodel等代码块标志后 - 无法输入界面名字等参数
- 生成的代码使用固定的占位符
、等 - 需要手动查找替换,效率低下
根本原因
代码片段使用了自定义占位符语法 ,而不是 VSCode 标准的 tabstop 语法 ${1:Name}。
自定义占位符是静态的,不支持交互式输入。
解决方案
1. 更新 Tabstop 语法
将所有静态占位符替换为 VSCode 标准 tabstop:
| 旧语法 | 新语法 | 说明 |
|---|---|---|
| ${1:Name} | 第1个可编辑参数 |
| ${2:Title} | 第2个可编辑参数 |
| ${2:ModelName} | 独立参数 |
| ${2:${1/(.*)/${1:/downcase}/}} | 自动转换为小写 |
| ../viewmodels/${2:${1/(.*)/${1:/downcase}/}_viewmodel}.dart | 自动生成导入路径 |
2. 修复 JSON 转义错误
修复了 flu.service.auth 中的无效转义序列:
diff
- "throw Exception('Login failed: \\${response.statusCode}');"
+ "throw Exception('Login failed: ${response.statusCode}');"3. 同步所有模板
更新了以下三个位置的 snippet 文件:
- ✅
packages/vscode-extension/snippets/dart.code-snippets - ✅
packages/core/templates/snippets/dart.code-snippets - ✅
packages/v2/templates/snippets/dart.code-snippets
更新的 Snippets
Page 相关
flu.stPage- Stateful 页面flu.lessPage- Stateless 页面flu.listPage- List 页面
Widget 相关
flu.stWidget- Stateful 组件flu.lessWidget- Stateless 组件flu.component- 通用组件
架构相关
flu.viewmodel- ViewModelflu.listViewModel- List ViewModelflu.model- Model
Service 相关
flu.service.api- API Serviceflu.service.auth- Auth Serviceflu.service.storage- Storage Service
使用示例
创建 Widget
之前:
dart
// 输入 stWidget 后生成:
class {{Name}}Widget extends StatefulWidget {
const {{Name}}Widget({super.key});
}
// 需要手动替换所有 {{Name}}现在:
dart
// 输入 stWidget 后:
// 1. 光标自动定位到 Name 位置
// 2. 输入 "MyButton"
// 3. 所有 ${1:Name} 自动替换为 "MyButton"
class MyButtonWidget extends StatefulWidget {
const MyButtonWidget({super.key});
}创建 Page
操作流程:
- 输入
stPage+ Tab - 输入页面名称,如
Home - Tab 跳过自动生成的导入路径
- 输入页面标题,如
首页 - 完成!
生成结果:
dart
import 'package:flutter/material.dart';
import '../base/base_page.dart';
import '../viewmodels/home_viewmodel.dart';
class HomePage extends BasePage<HomeViewModel> {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends BasePageState<HomeViewModel, HomePage> {
@override
String get title => '首页';
@override
HomeViewModel createViewModel() => HomeViewModel();
@override
Widget buildContent(BuildContext context) {
return Center(
child: Text('Home Page'),
);
}
}技术亮点
1. 智能名称转换
使用正则表达式自动转换命名格式:
json
"${2:${1/(.*)/${1:/downcase}/}_viewmodel}"- 输入:
HomePage - 自动生成:
homepage_viewmodel
2. 多位置同步替换
同一个 tabstop 编号(${1:Name})在代码中出现多次时,输入一次会同时替换所有位置。
3. 跳过自动生成的参数
自动生成的参数(如导入路径)可以直接按 Tab 跳过,无需手动输入。
验证方法
测试步骤
- 在任意 Flutter 项目中创建新的
.dart文件 - 输入
stWidget并按 Tab - 验证:
- ✅ 光标自动定位到
Name位置 - ✅ 输入名称后,所有相关位置同步更新
- ✅ 按 Tab 可以跳转到下一个参数
- ✅ 生成的代码符合项目规范
- ✅ 光标自动定位到
预期结果
- 所有
flu.*前缀的 snippet 都支持参数输入 - 参数之间可以用 Tab 键导航
- 自动转换功能正常工作
- 无 JSON 语法错误
后续建议
1. 更新文档
在 VSCode Extension 的 README 中添加 snippet 使用说明:
- 可用的 snippet 列表
- 参数说明
- 使用示例
- GIF 演示
2. 添加更多 Snippet
考虑添加:
flu.repository- Repository 模式flu.provider- Providerflu.cubit- Cubit (如果使用 Bloc)flu.test- 测试文件模板
3. 配置化
考虑在 Phase 7 中实现:
- 用户自定义 snippet
- 项目级 snippet 配置
- Snippet 模板生成器
相关文件
- 详细使用指南:
snippet-usage-guide.md - 修改的文件:
packages/vscode-extension/snippets/dart.code-snippetspackages/core/templates/snippets/dart.code-snippetspackages/v2/templates/snippets/dart.code-snippets
修复时间: 2025-12-01
影响范围: 所有 flu.* 前缀的代码片段
状态: ✅ 已完成并同步