knockout.js x Rails 4.2入門ガイド

最近仕事の関係で「Knockout.js
について勉強をしています。knockout.jsを選定した理由はレビューしてくれる経験者がチームにいたからです。
JSは不得手ですので、アドバイスをくれる同僚がいるのはほんとうに有にくい限りです。

knockout.jsのメリットは次の2つだと考えています。

- 機能が絞りこまれているので、学習コストが低い
- IE6+などの古いブラウザに対応しているので導入しやすい

今回はRailsに「Knockout.js」を組み込んだサンプルをいくつか紹介していきます。


サンプルソース

今回説明するサンプルのソースコードはGitHubで公開しています。

morizyun/knockout_rails_sample

Railsプロジェクトの作成

1
rails new app_name --skip-turbolinks --skip-bundle

Gemfileへの追加

Gemfileに以下を追加。

1
2
# knockout.js
gem 'knockoutjs-rails'

Gemをインストール

1
bundle install --path=vendor/bundle

knockout.jsの読み込み設定

app/assets/javascripts/application.jsに以下を追加。

1
//= require knockout

サンプルソースの導入

ここからはKnockout.jsのサンプルソースです。
簡単にこんなことができるんだなぁくらいの紹介です。

Textの監視・出力

Textを監視して、出力するスクリプト。まずはCoffeeScript

1
2
3
4
5
6
textViewModel = ->
self = this
self.message = ko.observable("")
return
ko.applyBindings textViewModel

続いてView側。

1
2
3
4
<input type="value" data-bind="value: message, valueUpdate: 'afterkeydown'"/>
<br/>
<br/>
<span data-bind="text: message"></span>

HTMLの監視・出力

HTMLを監視して、出力するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
htmlViewModel = ->
self = this
self.message = ko.observable("")
self.messageHtml = ko.computed((->
"<em>" + self.message() + "</em>"
), self)
return
ko.applyBindings htmlViewModel

続いてView側。

1
2
3
4
<input type="value" data-bind="value: message, valueUpdate: 'afterkeydown'"/>
<br/>
<br/>
<div data-bind="html: messageHtml"></div>

表示&非表示の制御

表示&非表示を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
visibleViewModel = ->
self = this
self.isTrue = true
self.isFalse = false
return
ko.applyBindings visibleViewModel

続いてView側。

1
2
3
4
5
6
<div data-bind="visible: isTrue">
Visible Sample Text for isTrue
</div>
<div data-bind="visible: isFalse">
Visible Sample Text for isFalse
</div>

CSSの制御

CSSを制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
cssViewModel = ->
self = this
self.isError = true
return
ko.applyBindings cssViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
10
11
<style type="text/css">
<!--
.error {
color: red;
}
-->
</style>
<div data-bind="css: {error: isError}">
CSS Sample Text
</div>

attr (htmlタグの属性) の制御

htmlタグの属性を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
attrViewModel = ->
self = this
self.hrefAttr = ko.observable(
href: 'http://www.google.co.jp'
title: 'Google'
)
return
ko.applyBindings attrViewModel

続いてView側。

1
2
3
<a href data-bind="attr: hrefAttr">
Attr Sample Text
</a>

checkbox (htmlタグ) の制御

checkboxを制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
checkboxViewModel = ->
self = this
self.items = ko.observableArray([
'hoge'
'piyo'
])
return
ko.applyBindings checkboxViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
<div>
<input type="checkbox" value="hoge" data-bind="checked: items" /> : hoge
</div>
<div>
<input type="checkbox" value="fuga" data-bind="checked: items" /> : fuga
</div>
<div>
<input type="checkbox" value="piyo" data-bind="checked: items" /> : piyo
</div>

foreach (繰り返し) の制御

foreach(繰り返し)を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foreachViewModel = ->
self = this
self.items = ko.observableArray([
'hoge'
'fuga'
'piyo'
])
self.addItem = ->
self.items.push('add')
self.removeItem = ->
self.items.pop()
return
ko.applyBindings foreachViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
10
<ul data-bind="foreach: { data: items, as: 'item' }">
<li><span data-bind="text: $index"></span> : <span data-bind="text: item"></span></li>
</ul>
<div>
<button data-bind="click: addItem">Add Item</button>
</div>
<div>
<button data-bind="click: removeItem">Remove Item</button>
</div>

select (htmlタグ) の制御

select (htmlタグ)を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
selectViewModel = ->
self = this
self.items = ko.observableArray([{
id: 11
name: 'HOGE'
}, {
id: 22
name: 'FUGA'
}, {
id: 33
name: 'PIYO'
}])
self.toId = (item) ->
"id_" + item.id
self.toLabel = (item) ->
"label_" + item.name
return
ko.applyBindings selectViewModel

続いてView側。

1
2
3
<div>
<select data-bind="options: items, optionsValue: toId, optionsText: toLabel"></select>
</div>

templateの管理

templateの管理に関するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
templateViewModel = ->
self = this
self.templateModel = ko.observable({ message: 'Hello Template!!' })
return
ko.applyBindings templateViewModel

続いてView側。

1
2
3
4
5
<div data-bind="template: {name: 'sampleTemplate', data: templateModel}"></div>
<script type="text/html" id="sampleTemplate">
<i data-bind="text: message"></i>
</script>

カスタムバインディング(custombinding) の制御

カスタムバインディング(custombinding) の制御に関するスクリプト。まずは、CoffeeScript

1
2
3
ko.bindingHandlers.myBinding = init: (element, valueAccessor, allBindings) ->
param = valueAccessor()
element.innerText = 'Custom Binding param = ' + param

続いてView側。

1
<div data-bind="myBinding: 101"></div>

本格的に勉強していくのに役立ちそうな資料

ここから、knockout.jsを勉強していくのにあたって役に立ちそうな資料のリンクを書いておきます。

あとがき

全体としては、たしかに学習コストが少なくて簡単に使い始められそうな印象です。
特定のことをやろうとした時にjQueryよりもわかりやすくコードを書けると思います。