Knockout.js チュートリアルのメモ:Creating custom bindings

Step 1

バインディングは双方向に働く。

アニメーションやスタイル、スターによるレーティングを実装する。

Step 2

ko.bindingHandlersにプロパティを追加することでバインディングを登録できる。バインディングには2つの関数initupdateを定義することで動作する。どちらの関数も結び付けられた要素と値を引数に持ったハンドラとなっている。

Step 3

外部ライブラリを内部で使用するのも問題なく可能となっている。

Step 4

ビューでの変更をビューモデルに伝えるには、引数の値を評価してobservableなプロパティを取得し、それに対して新しい値をセットすればよい。

具体的なDOM操作をカスタムバインディングの動作に閉じ込めることで、ビューを宣言的に記述できる。

Knockout.js チュートリアルのメモ:Single page applications

Step 1

最近のモダンでレスポンシブなWeb UIはSingle Page Applicationに向かっている。Single Page Applicationでは戻る/進むのサポートのためにhushベースまたはpushStateによるナビゲーションを使っている。

$dataはおそらくそのコンテキストでの対応するデータを参照する。例では、foreachで文字列のobservableな配列を列挙しているため、$dataは文字列そのものとなる。data-bind属性ではcssも制御できる。

Step 2

jQuery$.getのコールバックにobservableなプロパティを指定することで、$.getで取得されたデータがobservableなプロパティにセットされる => 変更が通知されてビューが更新される、という流れになっている。うまいことできてる。

withバインディングバインディングコンテキストを変更する。これにより、毎回プロパティを指定する手間が省ける。

Step 3

withバインディングで指定したプロパティがnullのときは対応する要素自体が表示されないようだ。

htmlバインディングは値をHTML要素としてビューに反映する。

Step 4

クライアントサイドのナビゲーションを実現するためのライブラリは沢山あるが、今回はsammy.jsというライブラリを使用する。Step 2で何の説明もなく出てきたjQueryもそうだけど、Knockout.js自体がシンプルにバインディングに特化している分、いろんなライブラリと組み合わせやすいようだ。逆に言えば、色んなライブラリを組み合わせないと他の全部入りクライアントサイドMVCフレームワークのようにはいかないということになりそうだ。ここらへんは人・組織によって好みが分かれるところだと思う。

コードを見る限り、sammy.jsはマッチするルートの処理を書けばあとは良しなにやってくれるようだ。あと、JavaScriptの「thisが何を指すかわかりにくい問題」に対応するために特に説明もなく導入されていたvar self = this;が、地味に重要な役割を果たしている。

Step 5

自分でDOM処理を書くことなく、よりきれいで簡単にクライアントサイドナビゲーションを実現できた。

今回はKnockout.jsを静的データに対するテンプレートシステム的に使用した。もちろん静的データに対してしか使えないということはない。Knockout.jsには、さまざまなreal worldのシナリオに対応するための豊富な機能がある。

Knockout.js チュートリアルのメモ:Working with Lists and Collections

Step 1

ko.observableArrayでobservableな配列を作成できる。observableな配列は要素の追加、削除についてobservableになっている。data-bind属性で子要素の繰り返しに指定するforeachはcontrol flow バインディングの一種。ほかにはifwhichなどがある。

Step 2

observableな配列へaddで要素を追加すると、対応するビューの要素も更新される。ビューに対しては全体を再描画するのではなく最小限のDOM更新で済ませるので、スケールするし、低性能のデバイスでも動作する。

Step 3

'options'バインディングで特定の値からの選択をバインディングできる。observableな配列の各要素について、observableなプロパティについてはその変更も監視される。逆に、observableでないプロパティについては変更は監視されないため、編集しても対応するビューの要素は更新されない。

Step 4

$rootはトップレベルのビューモデルを参照する。例のような行単位の削除は、各行に対応するオブジェクトではなくそのオブジェクト配列を管理するビューモデル側に処理を持たせることですっきりする。ko.computedはobservableな配列についてもしっかり計算できる。visibleバインディングは要素の表示非表示を、observableなプロパティを監視して制御する。

Step 5

MVVMな構造にすることで、簡単できれいに表示/状態/処理を連動させることができる。enableバインディングを使えば、条件によって活性/非活性を制御できる。

Knockout.js チュートリアルのメモ:Introduction

Knockout.jsのチュートリアルをやってみたので、その記録を残しておく。

Step 1

ビューの要素にdata-bind属性を付けると、ビューモデル => ビューのバインディングができる。ビューとビューモデルのバインディングについてはまだわからない。

Step 2

ko.observableでobservableを生成できる。ビューモデルのプロパティをobservableにすることで、双方向バインディングになる。

Step 3

observableなプロパティの値から何らかの計算をして別のプロパティとすることができる。このようなプロパティをcomputedプロパティとする。ko.computedに計算を渡すことで生成できる。計算内部で使用したobservableプロパティの変化に反応してcomputedプロパティも変化する。

Step 4

observableなプロパティはコードからも値の取得・設定ができる。

Step 5

Knockout.jsを使うことで、

  • ビューの状態を保持するデータをきれいでオブジェクト指向にのっとった形で書ける
  • 宣言的にビューを書ける
  • 「どうやってビューモデルに合わせてビューの状態を変えるか(また、その逆)」をフレームワークが面倒見てくれる

PowerShellで外部プログラムを実行する

PowerShellから外部プログラムを実行する場合は、

  • 直接exeを入力する
  • &
  • Start-Processコマンドレットを使用する

といった方法がる。

PS > notepad.exe test.txt
PS >

外部プログラムが空白を含むパスにある場合は、&を付ける(例ではPeaZipというアーカイバソフトを起動している)。

PS > & 'C:\Program Files\PeaZip\peazip.exe'
PS >

実行するとわかるが、すぐにプロンプトに制御が戻る。外部プログラムの完了を待ちたい場合は、

Start-Process -FilePath notepad.exe -ArgumentList test.txt -Wait

とStart-Processを-Waitを指定して実行すればよい。

PowerShellのハッシュテーブルとオブジェクト

PowerShellのハッシュテーブルは

#単一行
$hashTable = @{ 'Key1' = 'Value1', 'Key2' = 'Value2'}

#複数行
$hashTable = @{
    'Key1' = 'Value1'
    'Key2' = 'Value2'
}

といった形で作成できる。 要素へのアクセスは

# インデクサ
$hashTable['Key1']

#オブジェクト風
$hashTable.Key1

のように、通常のインデクサでの取得のほかに、オブジェクトのプロパティっぽく記述できる。PowerShell ISEなどで.を入力すると、インテリセンスの候補にも要素が表示される。

また、ハッシュテーブルをもとにオブジェクトを生成することもできる。というより、既存の型にハッシュテーブルを元にしたプロパティを生やしたようなオブジェクトを生成できる。

$obj = New-Object -TypeName PSObject -Property $hashTable

$obj.Key1 # -eq $hashTable.Key1

ハッシュテーブルでもオブジェクト風要素アクセスができるのであまり使いどころは思い浮かばないが、面白い機能だと思う。

PowerShellのコマンド履歴を保存/復元する

PowerShellのコマンド履歴は

Get-History

で取得できる。PowerShellはコマンド履歴をそのセッション中のものしか憶えていないため、PowerShellを起動しなおすとGet-Historyを実行しても空っぽだ。

これでは使いづらいので、セッション中のコマンド履歴を保存したり復元したりしたい。Get-Historyとコマンド履歴を追加するAdd-History、XMLシリアライズ/デシリアライズするExport/Import-Clixmlを利用することで、コマンド履歴をセッションをまたいで継続することができる。 履歴のファイルへの書き出しは

Get-History | Export-Clixml -path <履歴保存用ファイル>

ファイルから履歴への復元は

Import-Clixml -path <履歴保存用ファイル> | Add-History

復元した履歴は上下矢印キーでのプロンプトへの表示はできないが、

Get-History | where { <絞り込み> } | Invoke-History

などで実行できる。