Полезные Snippets для Flutter-разработчика

в 11:31, , рубрики: flutter, mobile apps, mobile development, snippets, мобильная разработка, разработка мобильных приложений

Всем привет! На связи Глеб Гусаров, flutter-разработчик в команде aim digital. Мы занимаемся разработкой цифровых продуктов и сервисов и автоматизацией процессов для бизнеса. В статье рассказываю, как создать файл конфигурации сниппетов и делюсь своей подборкой полезных сниппетов.

Полезные Snippets для Flutter-разработчика - 1

Snippet — это шаблон (подсказка в коде), по вызову которого можно быстро вставить готовый код.

В файле конфигурации сниппет представляет собой сущность в JSON имеющую ключ состоящую из двух полей:

  1. поле prefix — тип данных String — ключевое слово, при написании которого будет предложено использовать snippet

  2. поле body — массив String — код, который будет вставлен после применения snippet'a

Пример snippet'a :

"localizationImport": {    
"prefix": "localizationImport",    
"body": [        
"import 'package:perfluence_app/generated/l10n.dart';",     
],
}

Специальные возможности и регулярные выражения в snippet'ах

"t" — табуляция.

"$1" — место куда будет поставлен курсор после применения snippet'a, можно использовать $2, $3 и т.д. Цифра — это очередность позиции, куда встанет курсор после нажатия на Tab.

"$TM_FILENAME_BASE" — обращение к названию файла без расширения.

"${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}" — вернет название файла в CamelCase.

Как создать файл конфигурации Snippet'ов

  1. В Visual Studio code нажать комбинацию клавиш cmnd(ctrl) + shift + p   

  2. В появившемся поле ввести — Snippets 

  3. Выбрать в выпадающем меню пункт Preferences: Configure User Snippets и нажать Enter 

  4. Выбрать расширение файла, для которого будут использованы Snippet'ы (В нашем случае файлы с расширением .dart).  После чего создастся json-файл конфигурации Snippet'ов.

Полезные Snippets для Flutter-разработчика - 2

Примеры полезных сниппетов

Шаблон для дата классов (десериализация json_annotation +  equatable)

"dataClassFrom": {
    "prefix": "dataClassFrom",
     "body": [
         "import 'package:equatable/equatable.dart';",
        "import 'package:json_annotation/json_annotation.dart';",
        "",
        "part '$TM_FILENAME_BASE.g.dart';",
        "",
        "@JsonSerializable(",
        "tfieldRename: FieldRename.snake,",
        "tcreateToJson: false,",
        ")",
        "",
        "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends Equatable{",
        "tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}();",
        "",
        "tfactory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}.fromJson(Map<String, dynamic> json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}FromJson(json);",
        "",
        "t$1",
        "",
        "t@override",
        "tList<Object?> get props => [];",
        "}",
     ]
},

Шаблон для дата классов (десериализация, сериализация json_annotation +  equatable)

"dataClassToFrom": {
    "prefix": "dataClassToFrom",
    "body": [
         "import 'package:equatable/equatable.dart';",
        "import 'package:json_annotation/json_annotation.dart';",
        "",
        "part '$TM_FILENAME_BASE.g.dart';",
        "",
        "@JsonSerializable(",
        "tfieldRename: FieldRename.snake,",
        ")",
        "",
        "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends Equatable{",
        "tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}();",
        "",
        "tfactory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}.fromJson(Map<String, dynamic> json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}FromJson(json);",
        "",
        "tMap<String, dynamic> toJson() => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}ToJson(this);",
        "",
        "t$1",
        "",
        "t@override",
        "tList<Object?> get props => [];",
        "}",
     ]
},

Шаблон Stateless widget

"stateless": {
"prefix": "stless",
"body": [
"import 'package:flutter/material.dart';",
"",
"class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {",
"t@override",
"tWidget build(BuildContext context) {",
"ttreturn $1;",
"t}",
"}", 
]  
},

Шаблон Statefull widget

"statefull": {
"prefix": "stfull",
"body": [
"import 'package:flutter/material.dart';",
"",
"class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {",
"t@override",
"tState<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();",
"}",
"",
"class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {",
"t@override",
"tWidget build(BuildContext context) {",
"ttreturn $2;",
"t}",
"}",
]
},

Шаблон для быстрого создания цвета из HEX

"color": {
      "prefix": "color",
      "body": "const Color(0xFF$1)",
},

Шаблон для быстрого создания BoxShadow

"boxShadow": {
      "prefix": "bsh",
      "body": [
             "BoxShadow(",
             "tcolor: Colors.black.withOpacity(.5),",
             "toffset: const Offset(0, 0),",
             "tblurRadius: 0,",
             "),"
       ]
},

Шаблон для написания тестов arrange, act, assert 

"aaaTest": {
    "prefix": "aaaTest",
    "body": [
        "test(",
         "t'should $1',",
        "t() async {",
        "t//arrange",
        "t$2",
        "t//act",
        "t",
        "t//assert",
        "t},",
        ");",
    ],
},

Шаблон для создания интерфейса репозитория

"repo": {
   "prefix": "repo",
   "body": [
      "import '/core/error/failures.dart';",
      "import 'package:dartz/dartz.dart';",
      "",
      "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} {",
      "t$2",
      "}",
    ],
},

Шаблон для написания имплементации репозитория 

"repoImpl": {
    "prefix": "repoImpl",
   "body": [
      "import 'package:dartz/dartz.dart';",
      "import '/core/error/failures.dart';",
      "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} implements $1 {",
      "t@override",
      "tFuture<Either<Failure, $2>> getConcreteNumberTrivia() async {",
      "ttreturn const Left(DefaultFailure());",
      "t}",
      "}",
    ],
},

Шаблон для создания дата-класса параметров usecase

"usecaseParams": {
   "prefix": "usecaseParams",
   "body": [
      "import 'package:dartz/dartz.dart';",
      "import 'package:equatable/equatable.dart';",
      "import '/core/error/failures.dart';",
      "import '/core/usecases/usecase.dart';",
      "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}UC implements UseCase<$1, ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params> {",
      "tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}UC(this.repo);",
      "",
      "tfinal $2 repo;",
      "",
      "t@override",
      "tFuture<Either<Failure, $1>> call(${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params params) async {",
      "ttreturn await repo.$3();",
      "t}",
      "}",
      "",
      "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params extends Equatable {",
      "tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params();",
      "t@override",
       "tList<Object?> get props => [];",
      "}",
    ]
},

Автор: aim digital

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js