Mithril JS
Einar Norðfjörð
@nordfjord
What is Mithril
Mithril is a client-side MVC framework - a tool to organize code in a way that is easy to think about and to maintain.
What is mithril?
Light-weight | Robust | Fast |
---|---|---|
12kb gzipped | Safe-by-default templates | Virtual DOM diffing and compilable templates |
Small API | Hierarchical MVC via components | Intelligent auto-redrawing system |
Small learning curve |
How it compares
So how is it different?
- code size
- documentation
- Architecture
- View Layer Paradigm
Introduction to basic methods
- m
- m.mount
m(".container"); //<div class="container"></div>
m("#layout"); //<div id="layout"></div>
m("a[name=top]"); //<a name="top"></a>
m("[contenteditable]"); //<div contenteditable></div>
m("a#google.external[href='http://google.com']", "Google");
//<a id="google" class="external" href="http://google.com">Google</a>
m.mount(document.getElementById("content"), app);
Show me the code!
var app = {};
// notice the lack of boilerplate
app.view = function(){
return m('h1', 'Hello World!');
};
// mount the application
m.mount(document.body, app);
Two Way Data Binding?
var app = {};
app.controller = function () {
this.name = m.prop( '' );
};
app.view = function ( ctrl ) {
return [
m( 'input', {
value: ctrl.name(),
oninput: m.withAttr( 'value', ctrl.name )
} ),
m( 'h1', 'Hi ' + ctrl.name() )
];
};
m.mount( document.body, app );
Embracing Arrays
Users = {
list: function(){
return m.request({url: "users.json", method: "GET", initialValue: []});
}
};
var app = {};
app.controller = function () {
this.users = Users.list();
};
app.view = function ( ctrl ) {
return m("ul", [
ctrl.users().map(function(user){
return m( "li", user.name + ": @" + user.username );
})
]);
};
m.mount( document.body, app );
Embracing Functions
var app = {};
app.controller = function () {
this.data = [];
window.setInterval(function(){
for(var i = 0; i < 100; ++i){
this.data[i] = Math.random();
}
m.redraw();
}.bind(this), 20);
};
app.view = function ( ctrl ) {
return tableStyle(m('table', [
m('thead', m('tr', [m('th', 'Key'), m('th', 'Value')])),
m('tbody', [
ctrl.data.map(function(value, index){
return m('tr', [
m('td', index),
m('td', value)
]);
})
])
]));
};
m.mount( document.body, app );
function tableStyle(vdom){
vdom.attrs.className = 'table table-striped table-hover';
return vdom;
}
Integrating with existing libraries
var Select2 = {
view: function(f, ctrl) {
return m("select", {config: Select2.config(ctrl)}, [
ctrl.data.map(function(item) {
return m("option", {value: item.id}, item.name);
})
]);
}
};
Select2.config = function(ctrl) {
return function(element, isInitialized) {
var el = $(element);
if (!isInitialized) {
el.select2()
.on("change", function(e) {
if (typeof ctrl.onchange == "function") ctrl.onchange(el.select2("val"));
m.redraw();
});
}
el.select2("val", ctrl.value);
};
};
var app = {};
app.controller = function() {
var data = [{id: 1, name: "John"}, {id: 2, name: "Mary"}, {id: 3, name: "Jane"}];
var ctrl = {
data: data,
currentUser: data[1],
changeUser: function(id) {
ctrl.currentUser = data[id-1];
}
};
return ctrl;
};
app.view = function(ctrl){
return m("div", [
m("label", "User:"),
m.component(Select2, {data: ctrl.data, value: ctrl.currentUser.id, onchange: ctrl.changeUser})
]);
};
In Summary
Core | Routing | Data |
---|---|---|
m | m.route | m.request |
m.prop | m.route.param | m.deferred |
m.component | m.sync | |
m.mount | ||
m.withAttr |
Rendering | Html | |
---|---|---|
m.render | m.trust | |
m.redraw | ||
m.startComputation | ||
m.endComputation |
Demos available at https://github.com/nordfjord/mithrilexamples
deck
By Einar Norðfjörð
deck
- 1,744