代码片段
Flu CLI VSCode 扩展内置了 20+ 个 Dart 代码片段,帮助你快速生成常用代码。
使用方法
- 在
.dart文件中输入片段前缀 - 按
Tab键展开 - 使用
Tab在占位符间跳转 - 完成编辑
UI 组件片段
stWidget - StatefulWidget
前缀: stWidget
生成代码:
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return Container();
}
}使用场景: 创建有状态的组件
lessWidget - StatelessWidget
前缀: lessWidget
生成代码:
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}使用场景: 创建无状态的组件
stPage - StatefulWidget + ViewModel
前缀: stPage
生成代码:
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late final HomeViewModel _viewModel;
@override
void initState() {
super.initState();
_viewModel = HomeViewModel();
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Container(),
);
}
}使用场景: 创建带 ViewModel 的页面
lessPage - StatelessWidget + ViewModel
前缀: lessPage
生成代码:
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Container(),
);
}
}使用场景: 创建简单的页面
listPage - 列表页面
前缀: listPage
生成代码:
class UserListPage extends StatefulWidget {
const UserListPage({Key? key}) : super(key: key);
@override
State<UserListPage> createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
late final UserListViewModel _viewModel;
@override
void initState() {
super.initState();
_viewModel = UserListViewModel();
_viewModel.loadData();
}
@override
void dispose() {
_viewModel.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('User List'),
),
body: RefreshIndicator(
onRefresh: _viewModel.refresh,
child: ListView.builder(
itemCount: _viewModel.items.length,
itemBuilder: (context, index) {
final item = _viewModel.items[index];
return ListTile(
title: Text(item.toString()),
);
},
),
),
);
}
}使用场景: 创建列表页面,带下拉刷新
逻辑层片段
viewmodel - 基础 ViewModel
前缀: viewmodel
生成代码:
import 'package:flutter/foundation.dart';
class HomeViewModel extends ChangeNotifier {
// 状态
bool _isLoading = false;
bool get isLoading => _isLoading;
// 初始化
Future<void> init() async {
// TODO: 初始化逻辑
}
// 业务逻辑
Future<void> loadData() async {
_isLoading = true;
notifyListeners();
try {
// TODO: 加载数据
} catch (e) {
debugPrint('Error: $e');
} finally {
_isLoading = false;
notifyListeners();
}
}
@override
void dispose() {
// TODO: 清理资源
super.dispose();
}
}使用场景: 创建 ViewModel 类
listViewModel - 列表 ViewModel
前缀: listViewModel
生成代码:
import 'package:flutter/foundation.dart';
class UserListViewModel extends ChangeNotifier {
// 状态
bool _isLoading = false;
bool get isLoading => _isLoading;
List<dynamic> _items = [];
List<dynamic> get items => _items;
int _page = 1;
bool _hasMore = true;
// 加载数据
Future<void> loadData() async {
if (_isLoading || !_hasMore) return;
_isLoading = true;
notifyListeners();
try {
// TODO: 加载数据
// final data = await service.getList(page: _page);
// _items.addAll(data);
// _hasMore = data.isNotEmpty;
// _page++;
} catch (e) {
debugPrint('Error: $e');
} finally {
_isLoading = false;
notifyListeners();
}
}
// 刷新
Future<void> refresh() async {
_page = 1;
_hasMore = true;
_items.clear();
await loadData();
}
@override
void dispose() {
super.dispose();
}
}使用场景: 创建列表 ViewModel,带分页和刷新
model - 数据模型
前缀: model
生成代码:
class UserModel {
final String id;
final String name;
UserModel({
required this.id,
required this.name,
});
// 从 JSON 创建
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'] as String,
name: json['name'] as String,
);
}
// 转换为 JSON
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
// 复制并修改
UserModel copyWith({
String? id,
String? name,
}) {
return UserModel(
id: id ?? this.id,
name: name ?? this.name,
);
}
}使用场景: 创建数据模型类
service - 服务类
前缀: service
生成代码:
import 'package:http/http.dart' as http;
import 'dart:convert';
class UserService {
final String baseUrl = 'https://api.example.com';
// GET 请求
Future<Map<String, dynamic>> getUser(String id) async {
final response = await http.get(
Uri.parse('$baseUrl/users/$id'),
);
if (response.statusCode == 200) {
return json.decode(response.body);
} else {
throw Exception('Failed to load user');
}
}
// POST 请求
Future<Map<String, dynamic>> createUser(Map<String, dynamic> data) async {
final response = await http.post(
Uri.parse('$baseUrl/users'),
headers: {'Content-Type': 'application/json'},
body: json.encode(data),
);
if (response.statusCode == 201) {
return json.decode(response.body);
} else {
throw Exception('Failed to create user');
}
}
}使用场景: 创建 API 服务类
component - 通用组件类
前缀: component
生成代码:
import 'package:flutter/material.dart';
class UserCard extends StatelessWidget {
final String title;
final VoidCallback? onTap;
const UserCard({
Key? key,
required this.title,
this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(title),
),
),
);
}
}使用场景: 创建可复用的组件
Provider 片段
providerPage - Provider 页面
前缀: providerPage
生成代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => HomeViewModel(),
child: Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Consumer<HomeViewModel>(
builder: (context, viewModel, child) {
return Container();
},
),
),
);
}
}使用场景: 创建使用 Provider 的页面
consumer - Consumer Widget
前缀: consumer
生成代码:
Consumer<HomeViewModel>(
builder: (context, viewModel, child) {
return Container();
},
)使用场景: 快速创建 Consumer
selector - Selector Widget
前缀: selector
生成代码:
Selector<HomeViewModel, bool>(
selector: (context, viewModel) => viewModel.isLoading,
builder: (context, isLoading, child) {
return Container();
},
)使用场景: 创建性能优化的 Selector
GetX 片段
getxPage - GetX 页面
前缀: getxPage
生成代码:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final controller = Get.put(HomeController());
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Obx(() => Container()),
);
}
}使用场景: 创建使用 GetX 的页面
getxController - GetX Controller
前缀: getxController
生成代码:
import 'package:get/get.dart';
class HomeController extends GetxController {
// 响应式状态
final _isLoading = false.obs;
bool get isLoading => _isLoading.value;
@override
void onInit() {
super.onInit();
// TODO: 初始化
}
// 业务逻辑
Future<void> loadData() async {
_isLoading.value = true;
try {
// TODO: 加载数据
} catch (e) {
print('Error: $e');
} finally {
_isLoading.value = false;
}
}
@override
void onClose() {
// TODO: 清理资源
super.onClose();
}
}使用场景: 创建 GetX Controller
工具类片段
singleton - 单例模式
前缀: singleton
生成代码:
class AppConfig {
AppConfig._();
static final AppConfig _instance = AppConfig._();
static AppConfig get instance => _instance;
// 属性和方法
}使用场景: 创建单例类
future - Future 方法
前缀: future
生成代码:
Future<void> methodName() async {
try {
// TODO: 异步操作
} catch (e) {
debugPrint('Error: $e');
}
}使用场景: 快速创建异步方法
stream - Stream 方法
前缀: stream
生成代码:
Stream<int> countStream() async* {
for (int i = 0; i < 10; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}使用场景: 创建 Stream
自定义片段
你可以创建自己的代码片段:
步骤 1:打开片段设置
- 打开命令面板(
Cmd+Shift+P/Ctrl+Shift+P) - 输入
Preferences: Configure User Snippets - 选择
dart.json
步骤 2:添加片段
{
"My Custom Widget": {
"prefix": "mywidget",
"body": [
"class ${1:MyWidget} extends StatelessWidget {",
" const ${1:MyWidget}({Key? key}) : super(key: key);",
"",
" @override",
" Widget build(BuildContext context) {",
" return ${2:Container}();",
" }",
"}"
],
"description": "My custom widget template"
}
}步骤 3:使用片段
在 .dart 文件中输入 mywidget,按 Tab 展开。
片段变量
片段支持以下变量:
| 变量 | 说明 | 示例 |
|---|---|---|
${1:placeholder} | 第一个占位符 | ${1:MyWidget} |
${2:placeholder} | 第二个占位符 | ${2:Container} |
$1 | 引用第一个占位符 | class $1 |
$TM_FILENAME_BASE | 文件名(无扩展名) | home_page |
$TM_DIRECTORY | 目录名 | pages |
最佳实践
1. 使用一致的命名
- Page 片段:
xxxPage - ViewModel 片段:
xxxViewModel - Widget 片段:
xxxWidget
2. 合理使用占位符
{
"body": [
"class ${1:MyWidget} extends StatelessWidget {",
" const ${1:MyWidget}({Key? key}) : super(key: key);",
" // 使用 $1 引用第一个占位符",
"}"
]
}3. 添加描述
{
"description": "Create a stateless widget with custom styling"
}4. 分组管理
将相关片段放在一起:
{
"// UI Components": {},
"StatefulWidget": { ... },
"StatelessWidget": { ... },
"// ViewModels": {},
"ViewModel": { ... },
"ListViewModel": { ... }
}常见问题
片段不生效?
- 确认文件类型是
.dart - 检查片段前缀是否正确
- 尝试重启 VSCode
如何查看所有片段?
- 打开命令面板(
Cmd+Shift+P/Ctrl+Shift+P) - 输入
Insert Snippet - 查看可用片段列表
片段冲突怎么办?
如果多个扩展提供相同前缀的片段:
- 输入前缀后会显示多个选项
- 使用方向键选择需要的片段
- 按
Tab或Enter展开
如何分享片段?
- 导出
dart.json文件 - 分享给团队成员
- 团队成员复制到自己的片段文件中