Javascript 从布局组件中的文件加载时,如何避免无限循环?

Javascript 从布局组件中的文件加载时,如何避免无限循环?,javascript,mithril.js,Javascript,Mithril.js,我正在通过中的简单应用程序示例和中的布局示例,使用Mithril JS构建一个个人网页。但我一直在运行一个无限循环,其中有一个组件需要从文件加载数据 如果我通过“vnode.attrs”将内部文件加载组件传递给布局组件,则布局组件不会循环。但是,如果我在函数中使用内部组件构建布局组件,它会循环。我无法理解其中的区别 失败的例子: hello.json index.html 这里,路由“/workinghello”起作用,但“/hello”进入循环。为什么?“/workinghello”设计对我来

我正在通过中的简单应用程序示例和中的布局示例,使用Mithril JS构建一个个人网页。但我一直在运行一个无限循环,其中有一个组件需要从文件加载数据

如果我通过“vnode.attrs”将内部文件加载组件传递给布局组件,则布局组件不会循环。但是,如果我在函数中使用内部组件构建布局组件,它会循环。我无法理解其中的区别

失败的例子:

hello.json

index.html


这里,路由“/workinghello”起作用,但“/hello”进入循环。为什么?“/workinghello”设计对我来说似乎是一种代码味道,因为“vnode.attrs”通常只用于将数据传递给文档中的组件,而不是组件本身。是否有一种方法可以修复“/hello”或简化“/workinghello”?

仅从初始读取:
layout
返回一个函数,而
workingLayout
似乎只是定义一个函数,然后退出(不返回任何内容)。这包括对
m(…)
的调用,但如果对
m(…)
的调用正在调用返回的函数,则会有一个循环


作为一种良好的调试策略,当您有一个工作示例和一个非工作示例时,对其中一个示例进行小的更改,使其更像另一个示例,然后进行测试,然后重复,直到您要更改的示例的行为切换为与您要更改的示例的行为相同。然后前后切换该更改,并测试行为是否随该更改而前后更改,以确认此特定更改是否会产生差异。这是制作渲染的一部分,通常会帮助您直接解决问题。

问题在于我对布局组件以及
m.render的行为的误解。这个精确的行为在[文档](}的“包装布局组件”一节中得到了解决。
Hello.load
的响应触发了一个重画,该调用再次呈现
/Hello
路由,导致无限循环。我能够用以下设计清理路由(如doc链接中所建议的)。如果布局组件定义为:

var fixedLayout = {
    view: function(vnode) {
        return vnode.children
    }
}
路由器使用如下组件:

    "/fixedhello": {
        render: function() {
            return m(fixedLayout, m(HelloBox))
        }
    }

没有循环。

为什么
layout
遵循另一种模式而不是
workingLayout
?我想这可能是问题所在,甚至是您的
render:
方法-它们的实现方式也不相同。我不熟悉mithril.js,但尝试以相同的方式来实现这只是一个示例,说明了什么是有效的,什么是无效的't.我目前的组件设计类似于“/workingLayout”模式,但我试图理解为什么“layout”函数在使用时会导致循环。我相信您的问题与
返回{view:function(){}有关
您在
var layout
中添加了。Javascript有显式的返回语句,在函数执行结束时不会自动返回最后执行的语句。请尝试删除
return
语句,让我们知道发生了什么。您更改了此行为,这可能会导致奇怪的效果。请指向您在文档中找到此语法的确切页面,并向我们解释您尝试以不同方式执行此操作的原因。
var Hello = {
    loadedObj: {},
    load: function () {
        return m.request({
            method: "GET",
            url: "hello.json",
        }).then(function (result) { Hello.loadedObj = result })
    }
}

var HelloBox = {
    oninit: Hello.load,
    view: function () { return m("div", {}, Hello.loadedObj.text) }
}

var layout = function (comp) {
    return {
        view: function () { return m('div', {}, m(comp)) }
    }
}

var workingLayout = {
    view: function (vnode) { return m('div', {}, m(vnode.attrs.comp)) }
}

m.route(document.body, "/workinghello", {
    "/hello": {
        render: function () {
            console.log("rendering /hello")
            return m(layout(HelloBox))
        }
    },
    "/workinghello": {
        render: function () {
            console.log("rendering /workinghello")
            return m(workingLayout, { comp: HelloBox })
        }
    }
})
var fixedLayout = {
    view: function(vnode) {
        return vnode.children
    }
}
    "/fixedhello": {
        render: function() {
            return m(fixedLayout, m(HelloBox))
        }
    }