Cycle.js 驱动程序中可以有多个 DOM 对象吗?
Can there be more than one DOM object in the Cycle.js drivers?
到目前为止我找到的所有 Cycle.js 示例,在 run(main, drivers)
的 drivers
参数中使用一个名为 "DOM" 的 DOM
对象].是否可以有多个对象,例如,一个名为 "DOM1" 而另一个名为 "DOM2"?这样做的目的是在单个 HTML 页面中控制两个独立的动态 DOM 区域,以便在 index.html
中静态定义第三个 DOM 区域,并将其夹在中间在 DOM1 和 DOM2 之间。
作为附带问题,我看到的示例通常针对 ID 为 #app
或 #main-container
的 HTML div
,然后接收器是用 @cycle/dom
div
函数定义,因此在 div
中创建了一个不必要的 div
AFAICT。我还没有找到关于应该如何定义虚拟节点的明确解释或参考。假设上面的 DOM2 以 HTML form
元素为目标,并且应该包含两个 input
元素。它 有 像所有示例一样以 div
开头,还是可以直接在 .map
调用中定义 input
,以及如果可以,怎么做?
没有什么可以阻止您在应用程序中使用 DOM1
和 DOM2
接收器。 bloodyKnuckles 的例子完美地说明了这一点 https://esnextb.in/?gist=b54baa4131974b7f12d190fb63be8aeb
话虽如此,我不确定我是否真的明白这样做的意义。如果是性能问题,我认为将应用程序的呈现拆分为两个 DOM 驱动程序不会有太大好处。虚拟 DOM 库(在 cycle 的例子中是 snabbdom)被定制来识别 DOM 的片段,这些片段没有改变,只更新后者。
如果这是责任问题(DOM 的 2 个部分有非常不同的用途),那么我宁愿创建两个不同的循环应用程序,它们都在 DOM 的不同部分呈现。 (然后在主文件中调用 run
两次)
function app1(sources) {
return {
DOM: xs.of(div("hello from app1"))
}
}
function app2(sources) {
return {
DOM: xs.of(div("hello from app2"))
}
}
run(app1, {
DOM: makeDOMDriver("#app1")
})
run(app2, {
DOM: makeDOMDriver("#app2")
})
这样您就可以清楚地分离两个应用程序的关注点。
现在回答您的问题,即为什么需要将一块虚拟 DOM 包裹在 div
中。这是因为一块虚拟 DOM 必须有一个 单根 元素。换句话说:一段虚拟 DOM 必须是独立的(就像一个 HTML 文档只有一个 <html>
元素,它是根)。
实际上,这是一个很好的约束,因为它迫使您拥有独立的组件。在您给出的示例中(带有 <input>
字段),返回这样的 vDOM 绝对没有问题:
DOM: xs.of(input(/*...*/))
但是如果你的组件有一个input
和一个label
,那么你需要将它包装在另一个vNode
DOM: xs.of(div([label(/*...*/), input(/*...*/)])
到目前为止我找到的所有 Cycle.js 示例,在 run(main, drivers)
的 drivers
参数中使用一个名为 "DOM" 的 DOM
对象].是否可以有多个对象,例如,一个名为 "DOM1" 而另一个名为 "DOM2"?这样做的目的是在单个 HTML 页面中控制两个独立的动态 DOM 区域,以便在 index.html
中静态定义第三个 DOM 区域,并将其夹在中间在 DOM1 和 DOM2 之间。
作为附带问题,我看到的示例通常针对 ID 为 #app
或 #main-container
的 HTML div
,然后接收器是用 @cycle/dom
div
函数定义,因此在 div
中创建了一个不必要的 div
AFAICT。我还没有找到关于应该如何定义虚拟节点的明确解释或参考。假设上面的 DOM2 以 HTML form
元素为目标,并且应该包含两个 input
元素。它 有 像所有示例一样以 div
开头,还是可以直接在 .map
调用中定义 input
,以及如果可以,怎么做?
没有什么可以阻止您在应用程序中使用 DOM1
和 DOM2
接收器。 bloodyKnuckles 的例子完美地说明了这一点 https://esnextb.in/?gist=b54baa4131974b7f12d190fb63be8aeb
话虽如此,我不确定我是否真的明白这样做的意义。如果是性能问题,我认为将应用程序的呈现拆分为两个 DOM 驱动程序不会有太大好处。虚拟 DOM 库(在 cycle 的例子中是 snabbdom)被定制来识别 DOM 的片段,这些片段没有改变,只更新后者。
如果这是责任问题(DOM 的 2 个部分有非常不同的用途),那么我宁愿创建两个不同的循环应用程序,它们都在 DOM 的不同部分呈现。 (然后在主文件中调用 run
两次)
function app1(sources) {
return {
DOM: xs.of(div("hello from app1"))
}
}
function app2(sources) {
return {
DOM: xs.of(div("hello from app2"))
}
}
run(app1, {
DOM: makeDOMDriver("#app1")
})
run(app2, {
DOM: makeDOMDriver("#app2")
})
这样您就可以清楚地分离两个应用程序的关注点。
现在回答您的问题,即为什么需要将一块虚拟 DOM 包裹在 div
中。这是因为一块虚拟 DOM 必须有一个 单根 元素。换句话说:一段虚拟 DOM 必须是独立的(就像一个 HTML 文档只有一个 <html>
元素,它是根)。
实际上,这是一个很好的约束,因为它迫使您拥有独立的组件。在您给出的示例中(带有 <input>
字段),返回这样的 vDOM 绝对没有问题:
DOM: xs.of(input(/*...*/))
但是如果你的组件有一个input
和一个label
,那么你需要将它包装在另一个vNode
DOM: xs.of(div([label(/*...*/), input(/*...*/)])