「GET STARTED」で最終的にできあがるWebアプリの仕様
- テキストフィールドへ名前が入力されると、右側のバッジ部分に「名前 the 称号」と海賊っぽく表示する
- テキストフィールドが空の場合は、ボタンを押す度に「名前 the 称号」の組み合わせをランダムに表示する
- テキストフィールドが空かどうかで、ボタンのラベルを変える
- テキストフィールドへ入力すると、ボタンを無効化する
- テキストフィールドへ入力する度に「名前 the 称号」の組み合わせをランダムに表示する
- 「名前 the 称号」が変わる度に、名前と称号をローカルストレージへ保存する
Dartで書くときのポイントについて色々と気づき
- importでライブラリ全体をインポート。特定のクラスをインポートしたい場合はshowで
- final, staticなどはJavaと同じ意味で使用可能
- privateキーワードは無い。_を付けた変数がprivate扱いになる
- プログラムの実行主体はvoid main()
- 入出力ストリームの監視はlisten()で
- JavaScriptのPromisesと同じ扱いでFutureオブジェクトが使える。then()やcatchError()で、onSuccessとonErrorの扱いを切り分ける
- カスケードオペレーター(..)で、あるオブジェクトの複数のプロパティへアクセスできる
- window.localStorage['キー']でローカルストレージへアクセス
- List<String>などGenericsが使用可能
- getterは、戻り値 get プロパティと定義する。例えば、getPirateName()はString get pirateName
- => はreturn expr;の省略形として使える
- $は文字列内で変数を明示する時に使える(print('Error occurred: $error');)
- コンストラクタも定義できるPirateName(){}だけでなく、PirateName.fromJSON(){}といった定義も可能
- オプションの引数はcurly brackets({})で指定可能
- 型変換はasで(e.target as InputElement)
- querySelector()などでidを渡してDOM操作することになる。値のバインディングは Angularなどで別途自分でやる
「GET STARTED」で最終的にできあがるWebアプリのリソース
- piratebadge.css
- piratebadge.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Pirate badge</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="piratebadge.css">
</head>
<body>
<h1>Pirate badge</h1>
<div class="widgets">
<div>
<input type="text" id="inputName" maxlength="15" disabled>
</div>
<div>
<button id="generateButton" disabled>
Aye! Gimme a name!
</button>
</div>
</div>
<div class="badge">
<div class="greeting">
Arrr! Me name is
</div>
<div class="name">
<span id="badgeName"> </span>
</div>
</div>
<script type="application/dart" src="piratebadge.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
- piratenames.json : 名前と称号のリストを含んだJSONファイル
{ "names": [ "Anne", "Bette", "Cate", "Dawn",
"Elise", "Faye", "Ginger", "Harriot",
"Izzy", "Jane", "Kaye", "Liz",
"Maria", "Nell", "Olive", "Pat",
"Queenie", "Rae", "Sal", "Tam",
"Uma", "Violet", "Wilma", "Xana",
"Yvonne", "Zelda",
"Abe", "Billy", "Caleb", "Davie",
"Eb", "Frank", "Gabe", "House",
"Icarus", "Jack", "Kurt", "Larry",
"Mike", "Nolan", "Oliver", "Pat",
"Quib", "Roy", "Sal", "Tom",
"Ube", "Val", "Walt", "Xavier",
"Yvan", "Zeb"],
"appellations": [ "Awesome", "Captain",
"Even", "Fighter", "Great", "Hearty",
"Jackal", "King", "Lord",
"Mighty", "Noble", "Old", "Powerful",
"Quick", "Red", "Stalwart", "Tank",
"Ultimate", "Vicious", "Wily", "aXe", "Young",
"Brave", "Eager",
"Kind", "Sandy",
"Xeric", "Yellow", "Zesty"]}
- piratebadge.dart : Dartプログラム
// Import Dart Library.
import 'dart:html';
// 'show' keyword, which imports only the specified classes.
import 'dart:math' show Random;
import 'dart:convert' show JSON;
import 'dart:async' show Future;
// Declare button element as a global variable.
ButtonElement genButton;
// Declare span element as a global variable.
SpanElement badgeNameElement;
// key-value pairs string save to local storage.
final String TREASURE_KEY = 'pirateName';
// App starts here.
void main() {
// Stash the input element in a local variable.
InputElement inputField = querySelector('#inputName');
// Listen input streams.
inputField.onInput.listen(updateBadge);
genButton = querySelector('#generateButton');
genButton.onClick.listen(generateBadge);
badgeNameElement = querySelector('#badgeName');
// Call the function, which returns a Future(silimar to JavaScript Promises).
// Using underscore (_) as a parameter name indicates that the parameter is ignored.
PirateName.readyThePirates().then((_) {
// on success
inputField.disabled = false; // enable
genButton.disabled = false; // enable
// Retrieve the name from local storage.
setBadgeName(getBadgeNameFromStorage());
}).catchError((error) {
// '$' indicates that this is a variable, not a string.
print('Error initializing pirate names: $error');
badgeNameElement.text = 'Arrrr! No names.';
});
}
void updateBadge(Event e) {
// use 'as' to type casting
String inputName = (e.target as InputElement).value;
setBadgeName(new PirateName(firstName: inputName));
if (inputName.trim().isEmpty) {
// The cascade operator (..) allows you to perform multiple
// operations on the members of a single object.
genButton
..disabled = false
..text = 'Aye! Gimme a name!';
} else {
genButton
..disabled = true
..text = 'Arrr! Write yer name!';
}
}
void setBadgeName(PirateName newName) {
if (newName == null) {
return;
}
querySelector('#badgeName').text = newName.pirateName;
// Save the name to local storage.
window.localStorage[TREASURE_KEY] = newName.jsonString;
}
void generateBadge(Event e) {
setBadgeName(new PirateName());
}
// The function retrieves the name from local storage and
// creates a PirateName object from it.
PirateName getBadgeNameFromStorage() {
String storedName = window.localStorage[TREASURE_KEY];
if (storedName != null) {
return new PirateName.fromJSON(storedName);
} else {
return null;
}
}
// declare class
class PirateName {
// final variables cannot change.
static final Random indexGen = new Random();
// Declare generic type—List.
static List<String> names = [];
static List<String> appellations = [];
// Private variables start with underscore (_).
// Dart has no private keyword.
String _firstName;
String _appellation;
// Provide a constructor for the class.
// curly brackets{} indicates optional parameters.
PirateName({String firstName, String appellation}) {
if (firstName == null) {
_firstName = names[indexGen.nextInt(names.length)];
} else {
_firstName = firstName;
}
if (appellation == null) {
_appellation = appellations[indexGen.nextInt(appellations.length)];
} else {
_appellation = appellation;
}
}
// The constructor creates a new PirateName instance
// from a JSON-encoded string.
PirateName.fromJSON(String jsonString) {
Map storedName = JSON.decode(jsonString);
_firstName = storedName['f'];
_appellation = storedName['a'];
}
// Declare a class level method.
static Future readyThePirates() {
// If you spell miss the json file name,
// executes PirateName.readyThePirates().catchError() in main().
var path = 'piratenames.json';
// getString() returns Future is used as arguments
// to _parsePirateNamesFromJSON().
// then() is a callback function is called when the Future completes successfully.
return HttpRequest.getString(path).then(_parsePirateNamesFromJSON);
}
// Declare a instance and private method.
static _parsePirateNamesFromJSON(String jsonString) {
Map pirateNames = JSON.decode(jsonString);
names = pirateNames['names'];
appellations = pirateNames['appellations'];
}
// Provide a getter for the private variables
// The fat arrow ( => expr; ) syntax is a shorthand for { return expr; }.
String get pirateName => _firstName.isEmpty ? '' : '$_firstName the $_appellation';
// Add a getter to the PirateName class that encodes a pirate name in a JSON string.
String get jsonString => JSON.encode({
"f": _firstName,
"a": _appellation
});
}
実行は以下から確認できる。
Step6 Run the app.


0 件のコメント :
コメントを投稿