Mithril组件工作逻辑咨询 运行路由代码出现重复打印vnode的异常问题
重复打印vnode的原因与Mithril渲染逻辑说明
两次打印的直接触发链路
你观察到的两次vnode重复打印,本质是整个执行流程触发了两轮独立的路由渲染周期,是Mithril路由的默认工作逻辑带来的正常现象,既不是代码写错了,也不是运行出了异常:
- 当你调用
m.route(document.body, '/article/:articleid' ,{...})完成路由初始化时,Mithril会先检查当前浏览器URL是否能匹配到路由表中的规则。由于刚打开页面时URL没有对应路由内容,属于未匹配状态,Mithril会自动执行内部跳转,把当前URL设置为你传入的默认路由值——也就是字符串字面量/article/:articleid。这一轮跳转完成后,会首次匹配到对应Article组件,执行view函数,触发第一次控制台打印。这轮渲染里捕获到的articleid参数是字面量字符串:articleid,因为这个值是URL路径第二段的实际内容。 - 你在路由初始化执行完成后,紧接着又主动调用了
m.route.set('/article/:articleid', {articleid: 1})。这个方法的作用是将传入的路由模板和参数值拼接成真实可访问的路径,也就是把URL更新为/article/1。由于这次跳转后的URL和之前的URL(/article/:articleid)内容完全不同,Mithril会检测到路由状态变化,触发第二遍全量的根组件重渲染,再次执行Article组件的view函数,于是出现了第二次控制台打印,这轮渲染里的attrs.articleid就是你传入的数值1。
快速验证这个逻辑的方法
你可以做两个简单的对照测试确认触发来源:
- 删掉代码里自己写的那行
m.route.set(...),重新运行,此时控制台只会打印一次vnode,因为整个流程只有初始化时的一次路由跳转,没有第二次URL变化。 - 在两次打印的vnode输出里查看
attrs属性,第一次打印的对象里articleid是字符串":articleid",第二次打印的对象里articleid是数字1,这个属性值的差异可以直接对应两轮渲染的不同触发时机。
Mithril组件的核心工作逻辑补充
结合这个场景,也可以把Mithril组件的核心运行规则明确下来,避免后续遇到类似困惑:
- Mithril的组件
view方法不是只在组件首次挂载时执行一次,只要路由检测到URL变化触发了根组件重渲染,所有在当前渲染树里的组件view函数都会被重新调用,生成新的虚拟DOM节点参与diff对比。 - Mithril的路由切换判断核心是实际的浏览器URL值,只要两次set后的URL字符串存在差异,就会触发一次完整的视图更新流程,不会因为路由的匹配规则相同就跳过渲染。
另外可以提一个场景里的配置细节:你现在把带占位符的路由模式同时作为默认路由传入,其实不符合路由配置的最佳实践,默认路由应该是不带占位符的真实有效路径,比如直接传/article/1作为默认路径,就能减少一次无意义的占位符路径渲染。
内容的提问来源于stack exchange,提问作者pr0mpT_07
相关产品推荐
相关产品推荐

