Mithril 介绍

介绍

Mithril 是什么?

Mithril 是一个现代化的 JavaScript 框架,用于构建单页面应用。它非常小巧(< 8kb gzip),且内置了路由和 XHR 工具。

文件大小
Mithril (8kb)
Vue + Vue-Router + Vuex + fetch (40kb)
React + React-Router + Redux + fetch (64kb)
Angular (135kb)
性能
Mithril (6.4ms)
Vue (9.8ms)
React (12.1ms)
Angular (11.5ms)

很多知名公司,包括 Vimeo 和 Nike,以及开源平台 Lichess 等都在使用 Mithril。

如果你是有经验的前端开发者,想知道 Mithril 与其它库/框架的区别,请查看框架对比

Mithril 支持 IE9 及以上的所有浏览器。

起步

使用 Mithril 最简单的方式是直接从 CDN 引入 Mithril 文件,并按照本教程学习。本教程包含了大部分的 API,但只需花费你大概 10 分钟时间。

首先我们创建一个 HTML 文件:

<body>
    <script src="//unpkg.com/mithril/mithril.js"></script>
    <script>
    var root = document.body

    // your code goes here!
    </script>
</body>

Hello World

我们从最简单的开始,在页面中输出一段文本。添加下列代码到文件中:

var root = document.body

m.render(root, "Hello world")

下面来修改这段文本:

m.render(root, "My first app")

如你所见,创建和修改 HTML 用的是相同的代码。Mithril 会自动计算出最高效的方式来更新 HTML,并不会每次都重新创建 HTML。

DOM 元素

我们把文本包裹在 <h1> 标签中:

m.render(root, m("h1", "My first app"))

m() 函数可以描述任何 HTML 结构。例如在 <h1> 标签上添加一个类:

m("h1", {class: "title"}, "My first app")

例如创建多个元素:

[
    m("h1", {class: "title"}, "My first app"),
    m("button", "A button"),
]

以及创建嵌套的元素:

m("main", [
    m("h1", {class: "title"}, "My first app"),
    m("button", "A button"),
])

也可以通过一个 Babel 插件来直接使用 HTML 语法创建元素:

// HTML syntax via Babel's JSX plugin
<main>
    <h1 class="title">My first app</h1>
    <button>A button</button>
</main>

组件

组件是一个带 view 方法的对象:

var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "My first app"),
            m("button", "A button"),
        ])
    }
}

然后使用 m.mount 来激活组件:

m.mount(root, Hello)

激活组件后就生成了这样的元素:

<main>
    <h1 class="title">My first app</h1>
    <button>A button</button>
</main>

m.mount 的功能和 m.render 类似。但 m.render 只会渲染一次 HTML,而 m.mount 会激活 Mithril 的自动重绘系统。我们通过添加一个事件,来帮助理解这一概念:

var count = 0 // added a variable

var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "My first app"),
            // changed the next line
            m("button", {onclick: function() {count++}}, count + " clicks"),
        ])
    }
}

m.mount(root, Hello)

我们在按钮上定义了 onclick 事件,点击按钮时会增加 count 变量的值。同时把 count 的值渲染到了按钮文本中。

现在点击按钮,按钮的文本会自动更新。因为我们用了 m.mount,所以无需每次都调用 m.render 来修改按钮文本。

无需担心使用 m.mount 会带来性能问题。事实证明 Mithril 的渲染更新是非常快的,因为它只会涉及到 DOM 中需要更新的部分。例如上例中,点击按钮时,唯一需要更新的就是文本。

路由

路由功能用于在多个页面之间相互跳转。

我们来创建一个组件,这个组件包含一个链接:

var Splash = {
    view: function() {
        return m("a", {href: "#!/hello"}, "Enter!")
    }
}

该链接的 #!部分称为 hashbang,/hello 部分则是路由路径。

要有多个页面,我们使用 m.route

m.route(root, "/splash", {
    "/splash": Splash,
    "/hello": Hello,
})

m.route 具有和 m.mount 相同的自动重绘功能。但 m.route 还具有 URL 感知功能,它能自动感知到带 !# 的 URL。

m.route 函数的第二个参数是默认路由,如果 URL 中的 hashbang 指向的路由未定义,那么将自动重定向到默认路由。

XHR

XHR 是与服务器通信的方式。

我们修改上面的点击计数器的例子,使它能把数据保存到服务器。我们需要调用 m.request 函数:

var count = 0
var increment = function() {
    m.request({
        method: "PUT",
        url: "//rem-rest-api.herokuapp.com/api/tutorial/1",
        data: {count: count + 1},
        withCredentials: true,
    })
    .then(function(data) {
        count = parseInt(data.count)
    })
}

现在调用 increment 方法会把 count 的值发送到 /api/tutorial/1 接口,接口会返回更新后的 count 值。注意,count 变量只有在请求完成后才会更新。

我们把之前的组件中的事件处理替换成调用 increment 函数:

var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "My first app"),
            m("button", {onclick: increment}, count + " clicks"),
        ])
    }
}

现在单击按钮就能把 count 值保存到服务器了。

总结

我们已经介绍了如何创建和更新 HTML,如何为单页面应用创建组件和路由,以及如何通过 XHR 与服务器交互。

现在你已经熟悉了 Mithril API 的基础指示,继续阅读这个简单应用的教程,该教程会指导你构建一个真正的应用。