【前端骚操作】MithrilJS核心m函数
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 or Object | Yes | CSS 选择器或 m 对象(如上) |
attributes | Object | No | HTML 标签属性或自定义属性(无需 data-) |
children | Array or String or Number or Boolean | No | 数组,其他不推荐 |
returns | Vnode | 虚拟 DOM |
按照推荐写法,上面例子如下:
m('.parent', [m('.child')])
原因:
- 数组易拓展。
- 编辑器排版,这个你可以使用编辑器格式化试试看。
所以这里推荐,所有含有子 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.mount
或 m.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()
小结
- 推荐写法,子组件使用数组包起来
- 单实例
- 组件化,子组件使用
m()
包起来 - 传参,获取 vnode 方式
- redraw,不自动重新渲染的时候手动调用
欢迎关注,如有需要 Web,App,小程序,请留言联系。
共同学习,写下你的评论
评论加载中...
作者其他优质文章