Skip to content

Snippet 参数输入修复总结

问题描述

用户反馈在使用代码片段(snippet)创建 widget 时,无法传递参数:

  • 输入 stWidgetviewmodel 等代码块标志后
  • 无法输入界面名字等参数
  • 生成的代码使用固定的占位符
  • 需要手动查找替换,效率低下

根本原因

代码片段使用了自定义占位符语法 ,而不是 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 - ViewModel
  • flu.listViewModel - List ViewModel
  • flu.model - Model

Service 相关

  • flu.service.api - API Service
  • flu.service.auth - Auth Service
  • flu.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

操作流程:

  1. 输入 stPage + Tab
  2. 输入页面名称,如 Home
  3. Tab 跳过自动生成的导入路径
  4. 输入页面标题,如 首页
  5. 完成!

生成结果:

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 跳过,无需手动输入。

验证方法

测试步骤

  1. 在任意 Flutter 项目中创建新的 .dart 文件
  2. 输入 stWidget 并按 Tab
  3. 验证:
    • ✅ 光标自动定位到 Name 位置
    • ✅ 输入名称后,所有相关位置同步更新
    • ✅ 按 Tab 可以跳转到下一个参数
    • ✅ 生成的代码符合项目规范

预期结果

  • 所有 flu.* 前缀的 snippet 都支持参数输入
  • 参数之间可以用 Tab 键导航
  • 自动转换功能正常工作
  • 无 JSON 语法错误

后续建议

1. 更新文档

在 VSCode Extension 的 README 中添加 snippet 使用说明:

  • 可用的 snippet 列表
  • 参数说明
  • 使用示例
  • GIF 演示

2. 添加更多 Snippet

考虑添加:

  • flu.repository - Repository 模式
  • flu.provider - Provider
  • flu.cubit - Cubit (如果使用 Bloc)
  • flu.test - 测试文件模板

3. 配置化

考虑在 Phase 7 中实现:

  • 用户自定义 snippet
  • 项目级 snippet 配置
  • Snippet 模板生成器

相关文件

  • 详细使用指南: snippet-usage-guide.md
  • 修改的文件:
    • packages/vscode-extension/snippets/dart.code-snippets
    • packages/core/templates/snippets/dart.code-snippets
    • packages/v2/templates/snippets/dart.code-snippets

修复时间: 2025-12-01
影响范围: 所有 flu.* 前缀的代码片段
状态: ✅ 已完成并同步

Released under the MIT License.