Flutter 開發(fā)規(guī)范 僅供參考??

1.大駝峰?

類、枚舉、typedef和類型參數(shù)

class SliderMenu { ... }

class HttpRequest { ... }?

typedef Predicate = bool Function<T>(T value);

包括用于元數(shù)據(jù)注釋的類

class Foo { const Foo([arg]); }

@Foo(anArg) class A { ... }?

@Foo() class B { ... }

使用小寫加下劃線來命名庫和源文件

library peg_parser.source_scanner;?

import 'file_system.dart';

import 'slider_menu.dart';

不推薦如下寫法:

library pegparser.SourceScanner;?

import 'file-system.dart';

import 'SliderMenu.dart';

使用小寫加下劃線來命名導(dǎo)入前綴

import 'dart:math' as math;?

import 'package:angular_components/angular_components' as angular_components;

import 'package:js/js.dart' as js;

不推薦如下寫法:

import 'dart:math' as Math;

import 'package:angular_components/angular_components' as angularComponents;

import 'package:js/js.dart' as JS;

2.小駝峰

var item;?

HttpRequest httpRequest; void align(bool clearItems) { // ... }

優(yōu)先使用小駝峰法作為常量命名

const pi = 3.14;

const defaultTimeout = 1000;?

final urlScheme = RegExp('^([a-z]+):');?

class Dice { static final numberGenerator = Random(); }

不推薦如下寫法:

const PI = 3.14; const DefaultTimeout = 1000;

final URL_SCHEME = RegExp('^([a-z]+):');

class Dice { static final NUMBER_GENERATOR = Random(); }

不使用前綴字母

因為Dart可以告訴您聲明的類型、范圍、可變性和其他屬性,

所以沒有理由將這些屬性編碼為標(biāo)識符名稱。

defaultTimeout不推薦如下寫法:

kDefaultTimeout排序為了使你的文件前言保持整潔,我們有規(guī)定的命令,指示應(yīng)該出現(xiàn)在其中。

每個“部分”應(yīng)該用空行分隔。

3.引庫

在其他引入之前引入所需的dart庫

import 'dart:async';

import 'dart:html';

import 'package:bar/bar.dart';

import 'package:foo/foo.dart';

在相對引入之前先引入在包中的庫

import 'package:bar/bar.dart';?

import 'package:foo/foo.dart';?

import 'util.dart';

第三方包的導(dǎo)入先于其他包

import 'package:bar/bar.dart';

import 'package:foo/foo.dart';

import 'package:my_package/util.dart';

在所有導(dǎo)入之后,在單獨(dú)的部分中指定導(dǎo)出

import 'src/error.dart';

import 'src/foo_bar.dart';?

export 'src/error.dart';

不推薦如下寫法:

import 'src/error.dart';?

export 'src/error.dart';

import 'src/foo_bar.dart';

4.所有流控制結(jié)構(gòu),請使用大括號這樣做可以避免懸浮的else問題?

if (isWeekDay) {

print('Bike to work!');?

} else {

print('Go dancing or read a book!');

}

一個if語句沒有else子句,其中整個if語句和then主體都適合一行。

在這種情況下,如果你喜歡的話,你可以去掉大括號

if (arg == null) return defaultValue;

如果流程體超出了一行需要分劃請使用大括號:

if (overflowChars != other.overflowChars) {?

return overflowChars < other.overflowChars;?

}

不推薦如下寫法:

if (overflowChars != other.overflowChars)

return overflowChars < other.overflowChars;

注釋要像句子一樣格式化?除非是區(qū)分大小寫的標(biāo)識符,否則第一個單詞要大寫。

以句號結(jié)尾 ?(或“!”或“?”)。對于所有的注釋都是如此:doc注釋、內(nèi)聯(lián)內(nèi)容,甚至TODOs。

即使是一個句子片段。

greet(name) { // Assume we have a valid name. print('Hi, $name!'); }不推薦如下寫法:

greet(name) { /* Assume we have a valid name. */ print('Hi, $name!'); }

可以使用塊注釋(/…/)臨時注釋掉一段代碼,

但是所有其他注釋都應(yīng)該使用//Doc注釋?

使用///文檔注釋來記錄成員和類型。

使用doc注釋而不是常規(guī)注釋,可以讓dartdoc找到并生成文檔。

/// The number of characters in this chunk when unsplit. int get length => ...

考慮為私有api編寫文檔注釋?Doc注釋并不僅僅針對庫的公共API的外部使用者。

它們還有助于理解從庫的其他部分調(diào)用的私有成員以簡短的、

以用戶為中心的描述開始你的文檔注釋,以句號結(jié)尾。

/// Deletes the file at [path] from the file system. void delete(String path) { ... }

不推薦如下寫法:

/// Depending on the state of the file system and the user's permissions,?

/// certain operations may or may not be possible. If there is no file at

/// [path] or it can't be accessed, this function throws either [IOError]

/// or [PermissionError], respectively. Otherwise, this deletes the file.

void delete(String path) { ... }

字符串的使用優(yōu)先使用模板字符串?'Hello, $name! You are ${year - birth} years old.';

集合盡可能使用集合字面量?如果要創(chuàng)建一個不可增長的列表,或者其他一些自定義集合類型,

var points = [];?

var addresses = {};

var lines = <Lines>[];

不推薦如下寫法:

var points = List(); var addresses = Map();

不要使用.length查看集合是否為空

if (lunchBox.isEmpty) return 'so hungry...';?

if (words.isNotEmpty) return words.join(' ');

不推薦如下寫法:

if (lunchBox.length == 0) return 'so hungry...';?

if (!words.isEmpty) return words.join(' ');

考慮使用高階方法轉(zhuǎn)換序列?如果有一個集合,并且希望從中生成一個新的修改后的集合,

那么使用.map()、.where()和Iterable上的其他方便的方法通常更短,也更具有聲明性

var aquaticNames = animals .where((animal) => animal.isAquatic) .map((animal) => animal.name); ??

避免使用帶有函數(shù)字面量的Iterable.forEach()

5.循環(huán)/遍歷/賦值

在Dart中,如果你想遍歷一個序列,慣用的方法是使用循環(huán)。

for (var person in people) { ... }

不推薦如下寫法:

people.forEach((person) { ... });

不要使用List.from(),除非打算更改結(jié)果的類型?給定一個迭代,

有兩種明顯的方法可以生成包含相同元素的新列表

?var copy1 = iterable.toList();

?var copy2 = List.from(iterable);

明顯的區(qū)別是第一個比較短。

重要的區(qū)別是第一個保留了原始對象的類型參數(shù)

// Creates a List<int>: var iterable = [1, 2, 3];?

?// Prints "List<int>": print(iterable.toList().runtimeType);

// Creates a List<int>: var iterable = [1, 2, 3];?

?// Prints "List<dynamic>": print(List.from(iterable).runtimeType);

參數(shù)的使用使用=將命名參數(shù)與其默認(rèn)值分割開?由于遺留原因,Dart均允許“:”和“=”作為指定參數(shù)的默認(rèn)值分隔符。

為了與可選的位置參數(shù)保持一致,使用“=”。

void insert(Object item, {int at = 0}) { ... }

不推薦如下寫法:

void insert(Object item, {int at: 0}) { ... }

如果參數(shù)是可選的,但沒有給它一個默認(rèn)值,則語言隱式地使用null作為默認(rèn)值,因此不需要編寫它

void error([String message]) { stderr.write(message ?? '\n'); }

不推薦如下寫法:

void error([String message = null])

?{ stderr.write(message ?? '\n'); }

變量不要顯式地將變量初始化為空?在Dart中,未顯式初始化的變量或字段自動被初始化為null。

不要多余賦值

nullint _nextId;?

?class LazyId {?

?int _id;

?int get id {

?if (_nextId == null) _nextId = 0;

?if (_id == null) _id = _nextId++;

?return _id;

?} }

不推薦如下寫法:

int _nextId = null;?

?class LazyId {?

?int _id = null;

?int get id {

?if (_nextId == null) _nextId = 0;

?if (_id == null) _id = _nextId++; return _id;

?} }

避免儲存你能計算的東西?在設(shè)計類時,您通常希望將多個視圖公開到相同的底層狀態(tài)。

通常你會看到在構(gòu)造函數(shù)中計算所有視圖的代碼,然后存儲它們:

class Circle {?

?num radius;?

?num area;?

?num circumference;

?Circle(num radius) : radius = radius,?

?area = pi * radius * radius,?

?circumference = pi * 2.0 * radius;?

?}

如上代碼問題:

浪費(fèi)內(nèi)存緩存的問題是無效——如何知道何時緩存過期需要重新計算?

推薦的寫法如下:

class Circle {?

?num radius;?

?Circle(this.radius);

?num get area => pi * radius * radius;?

?num get circumference => pi * 2.0 * radius;

?}

類成員不要把不必要地將字段包裝在getter和setter中?

不推薦如下寫法:

class Box {

?var _contents;?

?get contents => _contents;?

?set contents(value) {

?_contents = value;

?} }

優(yōu)先使用final字段來創(chuàng)建只讀屬性 尤其對于 StatelessWidget在不需要的時候不要用this?

不推薦如下寫法:

class Box {?

?var value;?

?void clear() {

?this.update(null);?

?}?

?void update(value) {

?this.value = value;?

?} }

推薦如下寫法:

class Box {

?var value;?

?void clear() {

?update(null);?

?}?

?void update(value) {?

?this.value = value;

?} }

構(gòu)造函數(shù)盡可能使用初始化的形式?

不推薦如下寫法:

class Point {?

?num x, y;?

?Point(num x, num y) { this.x = x; this.y = y; } }

推薦如下寫法:

class Point { num x, y; Point(this.x, this.y); }

不要使用new?Dart2使new?

關(guān)鍵字可選推薦寫法:

Widget build(BuildContext context) {

?return Row( children: [

?RaisedButton( child: Text('Increment'), ), Text('Click!'),?

?], ); }

不推薦如下寫法:

Widget build(BuildContext context) {?

?return new Row( children: [

?new RaisedButton( child: new Text('Increment'), ), new Text('Click!'),

?], ); }

6.異步

異步優(yōu)先使用async/await代替原始的futures?async/await語法提高了可讀性,允許你在異步代碼中使用所有Dart控制流結(jié)構(gòu)。

Future<int> countActivePlayers(String teamName) async {?

?try {

?var team = await downloadTeam(teamName);?

?if (team == null) return 0;

?var players = await team.roster;

?return players.where((player) => player.isActive).length;

?} catch (e) { log.error(e); return 0; } }

當(dāng)異步?jīng)]有任何用處時,不要使用它?如果可以在不改變函數(shù)行為的情況下省略異步,那么就這樣做:

Future afterTwoThings(Future first, Future second) { return Future.wait([first, second]); }

不推薦寫法:

Future afterTwoThings(Future first, Future second) async { return Future.wait([first, second]); }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容