zweizhao.github.io

项目,文章,随笔,博客,Markdown,个人网站,人生感悟。

View on GitHub

m

紧接之前的 超好用的 Mithril.js 教程之核心概览,我们知道 m 函数是构建、渲染、数据绑定一体化的函数,他负责生成虚拟 DOM(后面使用 vnode 代替),并且绑定 data,承接 vnode 之间的数据传递关系,如:

m('.parent', m('.child'))

那么上面的 .child 就是 .parent 的子 vnode,而反过来 .parent 就是 .child 的父 vnode。

标准形式 m(selector, [attrs, children]) 后两者可选,可选表示请看:函数文档表示规范

一定要注意最后的 redraw,这个才是开发中最常见的坑。


本文核心

推荐写法

个人推荐

参数 类型 必选 描述
selector String | Object Yes CSS 选择器或 m 对象(如上)
attributes Object No HTML 标签属性或自定义属性(无需 data-)
children Array<VNode> | String | Number | Boolean No 数组,其他不推荐
returns Vnode   虚拟 DOM

按照推荐写法,上面例子如下:

m('.parent', [m('.child')])

原因:

  1. 数组易拓展。
  2. 编辑器排版,这个你可以使用编辑器格式化试试看。

所以这里推荐,所有含有子 vnode 的,全部使用数组,哪怕目前是只有一个。


单实例

m("div.class1#id1", { title: "title" }, "im div")

组件化

如果将上例的 .child 组件化,就是如下:

const Child = {
	view() {
		return m('.child')
	}
}

m('.parent', [m(Child)])

传参

上例传参如下:

const Child = {
	view(vnode) {
		console.log(vnode.attrs.param1) // im param1
		v.node.attrs.func1() // run func1
		return m('.child')
	}
}

m('.parent', [m(Child), { param1: 'im param1', func1: () => console.log('run func1') }])

建议单向数据流,子 vnode 修改父级数据什么的,通过回调函数处理,如上的 func1.

获取参数通过生命周期函数或 view 函数获取,共以下函数可获取:

函数 参数 函数描述
oninit vnode 初始化
oncreate vnode 创建真实 DOM 成功
onbeforeupdate vnode, old 组件 UI 内容刷新前
onupdate vnode 组件 UI 内容刷新后
onbeforeremove vnode 组件销毁前
onremove vnode 组件销毁
view vnode 组件 vnode 结构函数

redraw

这是问题关键!

m.mountm.route 渲染的结构树一般来说会根据数据更新来重新渲染,这个没问题。

但是当你使用 setTimeout / setInterval / requestAnimationFrame 以及第三方框架如 hammer.js 时候,便脱离了 Mithril 的数据监听流,此时修改绑定的数据便不会自动 diff 树且重新渲染了。

如果出现不自动渲染的情况,第一时间检查所处修改数据的上下文是否在上述情况中,具体表格如下:

上下文 是否自动渲染
常规情况 yes
m.request yes
m.jsonp yes
m.route yes,使用 m.route.set(),或 a 标签申明 m.route.link
m.route no,除上述情况外的特殊情况,不常见
oninit no
oncreate no
onupdate no
setTimeout no
setInterval no
requestAnimationFrame no
Promise no
第三方组件库 no

当页面出现上述情况,不自动渲染的情况下,使用 m.redraw() 即可强制重新渲染。

这里不用担心性能,因为本身自动渲染也是调用这个函数,这里只是给了一个迂回策略。

简单来说,绝大部分情况都是自动渲染的,如果开发出现不自动渲染,除了去找意外,最简单就是直接加上:m.redraw()


小结

  1. 推荐写法,子组件使用数组包起来
  2. 单实例
  3. 组件化,子组件使用 m() 包起来
  4. 传参,获取 vnode 方式
  5. redraw,不自动重新渲染的时候手动调用

如有收货,请关注一波。