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]); }