Flutter配置规则插件rules的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter配置规则插件rules的使用

Introduction

Rules 是一个简单而强大的验证库,适用于Dart和Flutter。它具有高度灵活性、易于理解、减少样板代码、自定义错误处理等功能,并且对Flutter友好。

Features

  • 高度灵活
  • 易于理解
  • 减少样板代码
  • 自定义错误处理
  • 覆盖单个错误
  • 与状态管理库兼容(如Mobx)

Installation

前往 https://pub.dev/packages/rules#-installing-tab- 获取最新版本的 rules

激活pre-commit hooks:

$ git config core.hooksPath .githooks/
$ chmod +x .githooks/pre-commit
$ chmod +x .githooks/pre-push

Concept

Rules库有三个部分:

  • Rule: 基本规则
  • GroupRule: 将基本规则组合在一起并进行验证
  • CombinedRule: 验证多个基本规则和组规则

Usage

导入库

import 'package:rules/rules.dart';

1. Rule (基本规则)

这是构建块的基础,所有验证从这里开始。

示例1

void main() {
  const textFieldValue = ''; // 或 const textFieldValue = null;

  final rule = Rule(
    textFieldValue,
    name: 'Text field',
    isRequired: true,
  );

  print(rule.error);
  // 输出: 'Text field is required'
  print(rule.hasError);
  // 输出: true

  if (rule.hasError) {
    // 错误处理
  } else {
    // 成功处理
  }
}

示例2

void main() {
  const textFieldValue = 'abc@xyz';

  final rule = Rule(
    textFieldValue,
    name: 'Text field',
    isRequired: true,
    isEmail: true,
  );

  print(rule.error);
  // 输出: 'Text field is not a valid email address'
  print(rule.hasError);
  // 输出: true

  if (rule.hasError) {
    // 错误处理
  } else {
    // 成功处理
  }
}

2. GroupRule

将基本规则组合在一起并进行验证。

示例

void main() {
  const textFieldValue1 = ''; // 或 const textFieldValue = null;
  const textFieldValue2 = '';

  final rule1 = Rule(
    textFieldValue1,
    name: 'Text field 1',
    isRequired: true,
  );

  final rule2 = Rule(
    textFieldValue2,
    name: 'Text field 2',
    isEmail: true,
  );

  final groupRule = GroupRule(
    [rule1, rule2], // value; List of Rule
    name: 'Group name', // placeholder value which will be used while displaying errors
  );

  print(groupRule.error);
  // 输出: 'Text field 1 is required'
  print(groupRule.hasError);
  // 输出: true
}

3. CombinedRule

管理多个 Rules 和 GroupRules。

示例

void main() {
  const textFieldValue1 = '';
  const textFieldValue2 = 'abc@xyz.com';

  final rule1 = Rule(
    textFieldValue1,
    name: 'Text field 1',
  ); // Validation OK
  final rule2 = Rule(
    textFieldValue2,
    name: 'Text field 2',
    isEmail: true,
  ); // Validation OK
  final groupRule = GroupRule([rule1, rule2],
      name: 'Group name', requiredAll: true); // Validation FAILED

  const textFieldValue3 = '';
  final rule3 = Rule(
    textFieldValue3,
    name: 'Text field 3',
    isRequired: true,
  ); // Validation FAILED

  final combinedRule = CombinedRule(
    rules: [rule3],
    groupRules: [groupRule],
  );

  print(combinedRule.errorList);
  // 输出: ['Text field 3 is required', 'All fields are mandatory in Group name']

  print(combinedRule.hasError);
  // 输出: true

  if (combinedRule.hasError) {
    // 错误处理
  } else {
    // 成功处理
  }
}

Flutter 示例

简单的表单验证

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String emailInput;
  String phoneInput;

  void _handleEmailTextFieldOnChange(String value) {
    setState(() {
      emailInput = value;
    });
  }

  void _handlePhoneTextFieldOnChange(String value) {
    setState(() {
      phoneInput = value;
    });
  }

  Rule get emailInputRule {
    return Rule(
      emailInput,
      name: 'Email',
      isAlphaSpace: true,
      isRequired: true,
      customErrorText: 'Invalid Email',
    );
  }

  Rule get phoneInputRule {
    return Rule(
      phoneInput,
      name: 'Phone',
      isPhone: true,
      isRequired: true,
      customErrorText: 'Invalid Phone',
    );
  }

  bool get isContinueBtnEnabled {
    final groupRule = GroupRule(
      [emailInputRule, phoneInputRule],
      name: 'Continue Button',
      requiredAll: true,
    );

    return !groupRule.hasError;
  }

  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
            TextField(
              onChanged: (String value) {
                _handleEmailTextFieldOnChange(value);
              },
              decoration: InputDecoration(
                hintText: 'Email address',
                errorText: emailInputRule?.error ?? null,
              ),
            ),
            TextField(
              onChanged: (String value) {
                _handlePhoneTextFieldOnChange(value);
              },
              decoration: InputDecoration(
                hintText: 'Phone',
                errorText: phoneInputRule?.error ?? null,
              ),
            ),
            if (isContinueBtnEnabled)
              FlatButton(
                onPressed: () {
                  // call api
                },
                child: const Text('Continue'),
              )
            else
              Container()
          ],
        ),
      ),
    );
  }
}

使用 Mobx 的表单验证

Mobx Store

class UpdateUserStore = _UpdateUserStoreBase with _$UpdateUserStore;

abstract class _UpdateUserStoreBase with Store {
  @observable
  String profileName;

  @observable
  String profileEmail;

  @computed
  Rules get profileNameInputRule {
    final rule = Rules(
      profileName,
      name: 'Name',
      isRequired: false,
      isAlphaSpace: true,
      customErrorText: 'Invalid name',
    );

    return rule;
  }

  @computed
  Rules get profileEmailInputRule {
    final rule = Rules(
      profileEmail,
      name: 'Email',
      isRequired: false,
      isEmail: true,
      customErrorText: 'Invalid email',
    );

    return rule;
  }

  @computed
  bool get isContinueButtonEnabled {
    final groupRule = GroupRules(
      [profileEmailInputRule, profileNameInputRule],
      name: 'Continue Button',
      requiredAll: true,
    );

    return !groupRule.hasError;
  }

  @action
  void setProfileName(String value) {
    profileName = value;
  }

  @action
  void setProfileEmail(String value) {
    profileEmail = value;
  }
}

Widget

class _UpdateUserScreen extends State<UpdateUserScreen> {
  UpdateUserStore _updateUserStore = UpdateUserStore();

  void _handleProfileNameOnChange(String value) {
    _updateUserStore.setProfileName(value);
  }

  void _handleProfileEmailOnChange(String value) {
    _updateUserStore.setProfileEmail(value);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: Display.getWidth(context),
      height: Display.getHeight(context),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Observer(
            builder: (_) {
              final _errorText = _updateUserStore.profileNameInputRule?.error;

              return TextField(
                onChanged: (String value) {
                  _handleProfileNameOnChange(value);
                },
                decoration: InputDecoration(
                  hintText: 'Name',
                  errorText: _errorText,
                ),
              );
            },
          ),
          Observer(
            builder: (_) {
              final _errorText = _updateUserStore.profileEmailInputRule?.error;

              return TextField(
                onChanged: (String value) {
                  _handleProfileEmailOnChange(value);
                },
                decoration: InputDecoration(
                  hintText: 'Email',
                  errorText: _errorText,
                ),
              );
            },
          ),
          Observer(
            builder: (_) {
              final _isContinueButtonEnabled =
                  _updateUserStore.isContinueButtonEnabled;

              if (!_isContinueButtonEnabled) {
                return Container();
              }

              return FlatButton(
                onPressed: () {},
                child: const Text('Continue'),
              );
            },
          ),
        ],
      ),
    );
  }
}

以上是关于如何在Flutter项目中使用rules插件进行数据验证的详细说明和示例代码。希望这些信息能帮助你在项目中更好地应用rules插件。


更多关于Flutter配置规则插件rules的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter配置规则插件rules的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中,配置规则插件(如lint规则)可以帮助开发者遵循一致的编码风格,减少潜在的错误,并提高代码的可读性和可维护性。Flutter通常使用pedantic包和dart analyze命令来执行这些规则。然而,从Dart 2.12开始,官方推荐使用package:lints作为新的lint规则集。

以下是如何在Flutter项目中配置和使用lint规则插件的步骤,包括相关的代码示例。

1. 添加package:lints到你的pubspec.yaml

首先,你需要在pubspec.yaml文件中添加package:lints依赖。

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  lints: ^1.0.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

2. 配置analysis_options.yaml

在你的项目根目录下(通常与pubspec.yaml同级),创建或编辑analysis_options.yaml文件,以包含lint规则配置。

include: package:lints/recommended.yaml

# 你可以在这里添加自定义规则覆盖,如果需要的话
# linter:
#   rules:
#     avoid_print: false  # 例如,禁用避免打印的规则

3. 应用lint规则

一旦配置完成,你可以通过运行flutter analyze命令来检查你的代码是否符合lint规则。任何不符合规则的地方都会在控制台中显示警告或错误。

4. 示例代码和lint规则的应用

假设你有以下简单的Flutter组件代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Lint Rules Example'),
        ),
        body: Center(
          child: Text('Hello, Flutter!'),
        ),
      ),
    );
  }
}

如果你的代码违反了任何lint规则(比如使用了不推荐使用的API,或者代码风格不符合规范),flutter analyze将会指出这些问题。

5. 修复lint问题

根据flutter analyze的输出,你可能需要调整你的代码。例如,如果lint规则提示某个变量未使用,你应该移除它或者标记为_unusedVariable(如果你确实需要保留它但暂时未使用)。

注意事项

  • 确保你的IDE(如VS Code或Android Studio)配置了Flutter和Dart插件,这样它们可以实时显示lint警告。
  • 定期检查并更新package:lints到最新版本,以获取最新的规则和最佳实践。
  • 在团队项目中,确保所有成员都遵循相同的lint规则配置,以保持代码风格的一致性。

通过以上步骤,你可以在Flutter项目中有效地配置和使用lint规则插件,以提高代码质量和团队协作效率。

回到顶部