Guide to Mithril.js
May 29, 2016
参考になるサンプルを Mithril.js Ver.0.2.5 で動くように修正し、ついでにコードをシンプルに調整してみました。
参考にしたページ
指定したElementへMithrilを使って表示
var azucic = m("div", "hogehoge.");
m.render(document.getElementById("azucic"), azucic);
styleを指定して表示
var style = { "font-style": "italic" };
var butamih = m("div", {style: style}, "hogehoge.");
m.render(document.getElementById("butamih"), butamih);
config
を使って表示後に指定した処理を実行
function sourceCopy(element) {
document.getElementById("vuzmofi-copy").innerHTML = element.innerHTML + "(copy from vuzmofi)";
}
m.render(document.getElementById("vuzmofi"), m("div", { config: sourceCopy }, "hogehoge."));
map を使ってリスト表示
var links = [
{title: "apple", url: "http://www.apple.com"},
{title: "google", url: "http://www.google.com"}
];
m.render(document.getElementById("abavo"), [
m("ul",
links.map(function(link) {
return m("li",
m("a", {href: link.url}, link.title)
);
})
)
]);
Viewを作って指定したElementへ表示
var efiera = {
view: function() {
return m("div", "hogehoge.");
}
};
m.mount(document.getElementById("efiera"), efiera);
変数を作って自動的にその値に書き換え
var ifeha = {
count: 0,
stab: function() {
this.count++;
},
view: function() {
return m("button.button.is-primary",
{onclick: this.stab.bind(this)},
"このボタンは " + this.count + " 回クリックされました。");
}
};
m.mount(document.getElementById("ifeha"), ifeha);
Attributeを引数に関数を実行できる m.withAttr()
のサンプル
var azwofnu = {
view: function() {
return [
m("div.control.has-addons", [
m(
"a.button",
{ onclick: m.withAttr("className", function(m) { alert(m); }) },
"このボタンのクラスは?"
),
m(
"a.button",
{ onclick: m.withAttr("tagName", function(m) { alert(m); }) },
"このボタンのタグは?"
),
m(
"button.button",
{ onclick: m.withAttr("tagName", function(m) { alert(m); }) },
"このボタンのタグは?"
)
]),
m("div", [
m(
"input[type=text].input",
{
value: "カーソルを合わせると内容をアラート表示",
onclick: m.withAttr("value", function(m) { alert(m); })
}
)
])
];
}
};
m.mount(document.getElementById("azwofnu"), azwofnu);
変数に自動的にgetter/setterが作成される m.prop()
のサンプル
var dejgikuf = {
text: m.prop(),
alert: function() {
var message = (this.text() == undefined)?
"何も入力されていません":
"\"" + this.text() + "\" が入力されています。";
alert(message);
},
view: function() {
return m("div.control.has-addons", [
m(
"input[type=text].input",
{
onchange: m.withAttr("value", this.text),
placeholder: "input here..."
}
),
m(
"button.button.is-primary.input-group-btn",
{ onclick: this.alert.bind(this) },
"Alert"
)
]);
}
}
m.mount(document.getElementById("dejgikuf"), dejgikuf);
Ajaxでデータを取得する m.request()
のサンプル
var azpek = {
data: m.prop(false),
url: "http://ratfactor.com/misc/lotr-fellowship.json.php",
click: function() {
m.request({
method: "GET",
url: this.url
}).then(this.data);
},
view: function() {
return this.data()?
m("p", this.data().description):
m("button.button.is-primary", { onclick: this.click.bind(this) }, "Load RSS");
}
}
m.mount(document.getElementById("azpek"), azpek);
m.route()
を使ってブックマークできるSPAのサンプル
var menu = {
view: function() {
return m("div.btn-group", [
btn("Page1", "/page1"),
btn("page2", "/page2")
]);
function btn(name, route) {
var isCurrent = (m.route() === route);
var click = function() { m.route(route); };
return m(
"button.button"+(isCurrent? ".is-primary": ""),
{onclick: click},
name
);
}
}
}
function Page(content, id) {
this.view = function() {
return [menu.view(), m("div.divider"), m(".page", m("p", content))];
}
}
var page1 = new Page("This is page1");
var page2 = new Page("This is page2");
// m.route.mode = "hash";
m.route(document.getElementById("cehofga"), "/page1", {
"/page1": page1,
"/page2": page2
});
controller
を利用したサンプル
var besiiw = {
controller: function() { this.value = "hogehoge."; },
view: function(ctl) { return m("div", "Value is " + ctl.value); }
}
m.mount(document.getElementById("besiiw"), besiiw);
ViewModelをつかった controller
のサンプル
var gagsestoj = {
vm: {
value: "hogehoge.",
echo: function() { return [0, 1].map(function(d) { return gagsestoj.vm.value; }).join(" ")},
clicked: false,
click: function() { this.clicked = true; }
},
controller: function() { this.vm = gagsestoj.vm; },
view: function(ctrl) {
return [
m("div", ctrl.vm.value),
m("button.button.is-primary", { onclick: function() { ctrl.vm.click(); } }, "echo"),
m("div", ctrl.vm.clicked? ctrl.vm.echo(): "")
];
}
};
m.mount(document.getElementById("gagsestoj"), gagsestoj);
Model, ViewModelを使い外部タイマーでの表示切替
// Modelを準備
// Modelは複数のコンポーネントから利用される可能性があるので外出しにする
var model = ["Eddie Benson", "Kenneth Wilson", "Tillie Barrett", "Curtis Gomez", "Russell Mitchell"];
// コンポーネントの作成
var caneti = {
// Viewで表示したり、Viewから書き込んだりするするViewModel
// もしModelを差し替えたくなったときはここでModelを切り替えるだけで済む
vm: {
names: model,
name: m.prop(),
value: m.prop()
},
// Viewからは全てCtrl経由でアクセスし、ModelへはViewModel経由でアクセス
controller: function() {
var self = this;
return {
vm: caneti.vm,
addName: function() {
caneti.vm.names.push(caneti.vm.value());
}
};
},
view: function(ctrl) {
return [
m("div", "names: [" + ctrl.vm.names.join(", ") + "]"),
m("div.control.has-addons", [
m(
"input[type=text].input",
{
onchange: m.withAttr("value", ctrl.vm.value),
placeholder: "input here..."
}
),
m("button.button.is-primary.input-group-btn", {onclick: ctrl.addName}, "add name")
]),
m("div", "random name: " + ctrl.vm.name())
];
}
};
// HTML表示
m.mount(document.getElementById("caneti"), caneti);
// 1sec毎にランダムに名前を表示
setInterval(function() {
// Mithrilにデータの変更開始を通知
m.startComputation();
// VMの名前を直接書き換え
var random = Math.floor(Math.random() * (model.length));
caneti.vm.name(model[random]);
// Mithrilにデータの変更完了を通知
m.endComputation();
}, 1000);