「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 件のコメント:
コメントを投稿