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;