On Github seqs / mithril-getting-started
Created by Seqs
http://matt-esch.github.io/mercury-perf/
构建虚拟DOM的便捷方法
m("br") => <br>
m("div", "Hello") => <div>Hello</div>
m("div", {class: "container"}, "Hello")
=> <div class="container">Hello</div>
m("div.container", "Hello")
=> <div class="container">Hello</div>
加载组件
var MyComponent = {
controller: function(args) {
return {greeting: args.message}
},
view: function(ctrl) {
return m("h2", ctrl.greeting)
}
}
var App = {
view: function() {
return m(".app", [
m("h1", "My App"),
// nested component
m.component(MyComponent, {message: "Hello"})
])
}
}
m.mount(document.body, App)
将组件渲染到DOM
var Hello = {
view: function(ctrl, props) {
return m("b", props.title);
}
};
m.mount(document.getElementById('root'), Hello);
getter/setter API
var myCtrl = function() {
this.name = m.prop('admaster');
console.log(this.name); // -> function(){..}
console.log(this.name()); // -> "admaster"
// change value
this.name('openmaster');
console.log(this.name()); // -> "openmaster"
};
配合onclick, oninput, onchange等事件使用
var user = {
model: function(name) {
this.name = m.prop(name);
},
controller: function() {
return {user: new user.model("John Doe")};
},
view: function(controller) {
m.render("body", [
m("input", {onchange: m.withAttr("value", controller.user.name), value: controller.user.name()})
]);
}
};
定义路由
m.route(document.body, "/", {
"/": Home,
"/login": Login,
"/dashboard": Dashboard,
});
m.route(document.body, "/files/pictures/pic1.jpg", {
"/files/:file...": gallery
});
m.route.param("file") === "pictures/pic1.jpg"
m.route(document.body, "/blog/2014/01/20/articles", {
"/blog/:date.../articles": articleList
});
m.route.param("date") === "2014/01/20"
重定向
m.route("/dashboard");
返回当前激活路由
获取路由参数
// a sample component
var Dashboard = {
controller: function() {
return {id: m.route.param("userID")}
},
view: function(controller) {
return m("div", controller.id);
}
}
// setup routes to start w/ the `#` symbol
m.route.mode = "hash";
// define a route
m.route(document.body, "/dashboard/johndoe", {
"/dashboard/:userID": Dashboard
});
m.route("/grid?sortby=date&dir=desc")
var sortBy = m.route.param("sortby") // "date"
var dir = m.route.param("dir") // "desc"
发起 ajax 请求
var users = m.request({method: "GET", url: "/user"});
var users = m.prop([]); // default value
m.request({method: "GET", url: "/user"}).then(users)
异步流程处理
// standalone usage
var greetAsync = function() {
var deferred = m.deferred();
setTimeout(function() {
deferred.resolve("hello");
}, 1000);
return deferred.promise;
};
greetAsync()
.then(function(value) {return value + " world"})
.then(function(value) {console.log(value)}); //logs "hello world" after 1 second
异步队列处理
var greetAsync = function(delay) {
var deferred = m.deferred();
setTimeout(function() {
deferred.resolve("hello");
}, delay);
return deferred.promise;
};
m.sync([
greetAsync(1000),
greetAsync(1500)
]).then(function(args) {
console.log(args); // ["hello", "hello"]
});
将虚拟DOM渲染到指定HTML element上
var links = [
{title: "item 1", url: "/item1"}
];
m.render(document.body, [
m("ul.nav", [
m("li", links.map(function(link) {
return m("a", {href: link.url, config: m.route}, link.title)
})
])
]);
重绘
var doStuff = function() {
var self = this;
self.text = m.prop();
setTimeout(function() {
self.text("hello");
m.redraw();
}, 1000);
};
绘制计算
var doStuff = function() {
var self = this;
self.text = m.prop();
m.startComputation(); //call `startComputation` before the asynchronous `setTimeout`
setTimeout(function() {
self.text("hello");
m.endComputation(); //call `endComputation` at the end of the callback
}, 1000);
};
Mithril 默认 HTML 安全过滤的,该方法输出原生 HTML
// assume this content comes from the server
var content = "<h1>Error: invalid user</h1>";
m.render("body", [
m("div", m.trust(content))
]);
输出
<body>
<div>
<h1>Error: invalid user</h1>
</div>
</body>
m("ul.things", [
m("li", "iPhone"),
m("li", "Macbook"),
])
m "ul.things", m "li", "iPhone" m "li", "Macbook"
<ul class="things"> <li>iPhone</li> <li>Macbook</li> </ul>
类似 xml 的语法,用来描述组件树
<div class="x"> <a href="#">#</a> <Hello>1</Hello> </div>
编译为
{tag: "div", attrs: {class:"x"}, children: [
{tag: "a", attrs: {href:"#"}, children: ["#"]},
m.component(Hello, {}, ["1"])
]}
可以通过 {变量名} 来将变量的值作为属性值
var x = "http://www.alipay.com";
var y = <a href={x}>Alipay</a>;
通过 props 我们可以获取传递给该组件的属性值
var Hello = {
view: function(ctrl, props) {
return <b>{props.title}</b>
}
};
可以通过设置原生 dom 组件的 onEventType 属性来监听 dom 事件,例如 onclick, onmousedown,在加强组件内聚性的同时,避免了传统 html 的全局变量污染
var LikeButton = {
view: function(ctrl) {
var text = ctrl.state.liked() ? 'like' : 'haven\'t liked';
return (
<p>
You {text} this.
<a href="javascript:;"
onclick={ctrl.handleClick}>Click</a> to toggle.
</p>
);
}
};
整合第三方基于DOM的类库,例如jquery.datepicker
var MyView = {
view: function(ctrl) {
return (
<div>
<input type="text"
config={function(element, init, context) {
if (init) { return false; }
$(element).datepicker();
}}/>
</div>
);
}
};
我们可以像使用原生 DOM 组件一样使用自定义的组件
var A = {
view: function() {
return <a href="#">a</a>;
}
};
var B = {
view: function() {
return <i><A /></i>;
}
};
自定义组件中我们可以通过 children 访问自定义组件的子节点
var NotesList = {
view: function(ctrl, props, children) {
return (
<ol>
{children.map(function(child) {
return (<li>{child}</li>);
})}
</ol>
);
}
};
var ComponentChildren = {
view: function(ctrl) {
return (
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>
);
}
};
module.exports = ComponentChildren;