Flutter特征文件夹管理插件feature_folder_cli_plus的使用

Flutter特征文件夹管理插件feature_folder_cli_plus的使用

简介

feature_folder_cli_plus 是一个Dart命令行工具,它基于“按功能组织文件夹”的模式生成文件夹结构。这个工具简化了为模型、服务、仓库、屏幕和小部件设置所需目录结构的过程,减少了重复的工作量。

该工具是基于原版 feature_folder_cli 进行改进的版本,因为原版已经一年多没有维护。新版本引入了增强功能和改进,使其更加健壮和与时俱进。

文件夹结构

CLI 为每个功能生成以下文件夹结构:

feature/
┣ domain/
┃ ┣ models/                    // 模型文件夹
┃ ┣ repository/                // 仓库文件夹
┃ ┣ services/                  // 服务文件夹
┃ ┗ index.dart                 // domain 文件夹的索引文件
┣ screens/
┃ ┣ feature_screen.dart        // 功能屏幕文件
┃ ┗ index.dart                 // screens 文件夹的索引文件
┣ widgets/
┃ ┣ feature_component.dart     // 功能组件文件
┃ ┗ index.dart                 // widgets 文件夹的索引文件
┣ providers/
┃ ┣ feature_provider.dart      // 功能提供者文件
┃ ┗ index.dart                 // providers 文件夹的索引文件
┗ index.dart                   // feature 文件夹的索引文件

命令用法

确保你在项目的根目录下执行以下命令:

ff generate -n <feature_name> -t <type> -p <path>
  • -n <feature_name>: 指定功能的名称。
  • -t <type>: 指定状态管理类型。支持的值有 provider, getx, cubit, 和 bloc
  • -p <path>: 指定创建功能文件夹的路径。
支持的状态管理类型
  • provider
  • getx
  • cubit
  • bloc

示例用法

以下是生成不同状态管理类型的功能文件夹的示例命令:

ff generate -n Example -t provider -p features
ff generate -n Example -t getx -p features
ff generate -n Example -t cubit -p features
ff generate -n Example -t bloc -p features

每条命令将根据指定的功能生成相应的文件夹结构和初始文件。

安装

要安装此工具,请运行以下命令:

dart pub global activate feature_folder_cli_plus

然后,确保 Dart 的 bin 目录已添加到系统的 PATH 中,以便全局使用 ff 命令。

许可证

该项目采用 MIT 许可证。详情请参阅 LICENSE 文件。


完整示例 Demo

假设我们要创建一个名为 user_profile 的功能,并使用 provider 作为状态管理方式。以下是完整的步骤和生成的文件结构:

1. 安装 feature_folder_cli_plus

首先,在终端中运行以下命令来安装工具:

dart pub global activate feature_folder_cli_plus

确保 Dart 的 bin 目录已添加到系统的 PATH 中。

2. 生成 user_profile 功能文件夹

在项目的根目录下,运行以下命令来生成 user_profile 功能文件夹:

ff generate -n user_profile -t provider -p features

3. 生成的文件结构

执行上述命令后,项目中的 features 文件夹将包含以下结构:

features/
┣ user_profile/
┃ ┣ domain/
┃ ┃ ┣ models/
┃ ┃ ┣ repository/
┃ ┃ ┣ services/
┃ ┃ ┗ index.dart
┃ ┣ screens/
┃ ┃ ┣ user_profile_screen.dart
┃ ┃ ┗ index.dart
┃ ┣ widgets/
┃ ┃ ┣ user_profile_component.dart
┃ ┃ ┗ index.dart
┃ ┣ providers/
┃ ┃ ┣ user_profile_provider.dart
┃ ┃ ┗ index.dart
┃ ┗ index.dart

4. 文件内容示例

user_profile/domain/models/user.dart
// 用户模型类
class User {
  final String id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }
}
user_profile/domain/repository/user_repository.dart
// 用户仓库接口
abstract class UserRepository {
  Future<User> getUser(String userId);
  Future<void> updateUser(User user);
}
user_profile/domain/services/user_service.dart
// 用户服务类
class UserService {
  final UserRepository _userRepository;

  UserService(this._userRepository);

  Future<User> fetchUser(String userId) async {
    return await _userRepository.getUser(userId);
  }

  Future<void> updateUserInfo(User user) async {
    await _userRepository.updateUser(user);
  }
}
user_profile/screens/user_profile_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../providers/user_profile_provider.dart';

class UserProfileScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final userProvider = Provider.of<UserProfileProvider>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('用户资料'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('用户名: ${userProvider.user?.name ?? '加载中...'}'),
            Text('邮箱: ${userProvider.user?.email ?? '加载中...'}'),
            ElevatedButton(
              onPressed: () {
                // 更新用户信息的逻辑
              },
              child: Text('更新资料'),
            ),
          ],
        ),
      ),
    );
  }
}
user_profile/providers/user_profile_provider.dart
import 'package:flutter/foundation.dart';
import '../domain/models/user.dart';
import '../domain/services/user_service.dart';

class UserProfileProvider with ChangeNotifier {
  final UserService _userService;
  User? _user;

  UserProfileProvider(this._userService);

  User? get user => _user;

  Future<void> loadUser(String userId) async {
    try {
      _user = await _userService.fetchUser(userId);
      notifyListeners();
    } catch (e) {
      if (kDebugMode) {
        print('Failed to load user: $e');
      }
    }
  }

  Future<void> updateUser(User updatedUser) async {
    try {
      await _userService.updateUserInfo(updatedUser);
      _user = updatedUser;
      notifyListeners();
    } catch (e) {
      if (kDebugMode) {
        print('Failed to update user: $e');
      }
    }
  }
}
user_profile/widgets/user_profile_component.dart
import 'package:flutter/material.dart';

class UserProfileComponent extends StatelessWidget {
  final String userName;
  final String userEmail;

  UserProfileComponent({required this.userName, required this.userEmail});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              '用户名: $userName',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 8),
            Text('邮箱: $userEmail'),
          ],
        ),
      ),
    );
  }
}

5. 使用 user_profile 功能

在主应用中,可以通过 ChangeNotifierProvider 来提供 UserProfileProvider,并在需要的地方使用 UserProfileScreen

main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'features/user_profile/screens/user_profile_screen.dart';
import 'features/user_profile/providers/user_profile_provider.dart';
import 'features/user_profile/domain/services/user_service.dart';
import 'features/user_profile/domain/repository/user_repository_impl.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<UserRepository>(
          create: (_) => UserRepositoryImpl(),
        ),
        ProxyProvider<UserRepository, UserService>(
          update: (_, userRepository, __) => UserService(userRepository),
        ),
        ChangeNotifierProvider<UserProfileProvider>(
          create: (context) => UserProfileProvider(
            Provider.of<UserService>(context, listen: false),
          )..loadUser('123'), // 假设用户ID为 '123'
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: UserProfileScreen(),
      ),
    );
  }
}

更多关于Flutter特征文件夹管理插件feature_folder_cli_plus的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter特征文件夹管理插件feature_folder_cli_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用feature_folder_cli_plus插件的一个示例。这个插件旨在帮助开发者更好地管理Flutter项目中的特性(feature)文件夹。

首先,你需要确保你的Flutter环境已经设置好,并且你的项目已经初始化。然后,你可以按照以下步骤来安装和使用feature_folder_cli_plus插件。

1. 安装feature_folder_cli_plus插件

在你的Flutter项目根目录下,打开终端并运行以下命令来安装插件:

dart pub global activate feature_folder_cli_plus

2. 配置环境变量(可选,但推荐)

为了方便使用,你可以将插件的全局可执行文件路径添加到你的系统PATH环境变量中。这样你就可以在任何地方通过命令行调用ffc命令了。

3. 创建特性文件夹

现在你可以使用ffc命令来创建特性文件夹了。例如,如果你想创建一个名为login的特性文件夹,你可以运行:

ffc create login

这个命令会在你的lib目录下创建一个名为features的文件夹(如果它还不存在的话),并在其中创建一个名为login的子文件夹。login文件夹中会包含以下文件结构:

lib/
└── features/
    └── login/
        ├── login_bloc.dart
        ├── login_event.dart
        ├── login_page.dart
        ├── login_repository.dart
        ├── login_state.dart
        └── login_widget.dart

注意:实际生成的文件和文件夹结构可能会根据插件的版本和配置有所不同。

4. 自定义模板(可选)

feature_folder_cli_plus允许你自定义生成的文件模板。你可以在项目的根目录下创建一个名为.ffc.yaml的配置文件,并在其中指定你的自定义模板。例如:

templates:
  page: |
    import 'package:flutter/material.dart';

    class {{feature_name_capitalized}}Page extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('{{feature_name_capitalized}} Page'),
          ),
          body: Center(
            child: Text('Welcome to the {{feature_name}} feature!'),
          ),
        );
      }
    }

在这个例子中,我们自定义了page模板,使其生成一个带有标题和欢迎信息的页面。

5. 使用生成的文件

现在你可以在你的Flutter应用中使用这些生成的文件了。例如,你可以在main.dart中导入并使用login_page.dart

import 'package:your_app_name/features/login/login_page.dart';

void main() {
  runApp(MaterialApp(
    home: LoginPage(),
  ));
}

请注意,上面的代码只是一个示例,实际使用时你可能需要根据你的应用结构和需求进行调整。

总结

通过以上步骤,你可以在Flutter项目中轻松地使用feature_folder_cli_plus插件来管理特性文件夹。这个插件不仅可以帮助你保持项目的结构清晰,还可以提高开发效率。

回到顶部