当组件位于两个单独的文件中时,如何在 ractive.js 中的另一个组件中插入和嵌套组件?

How to insert and nest a component within another in ractive.js when the components are in two separate files?

我已经学习 ractive.js 几周了,我正在尝试在列出三个项目的较大网页中构建一个功能。每个列表都有自己的标题和描述。每个列表都是一个组件 (list-component),具有自己的样式和 javascript(每个组件都是一个单独的 html)。我还有一个组件 (description-component) 负责写出标题和描述,它位于单独的 html 文件中。我遇到的问题是 'importing' 或将 description-component 引入 list-component 所以主索引 html 文件中的输出是这样的:

<description title="Name">
    <list-items/>
</description>

到目前为止,我研究了 yield 指令并尝试了一些示例,但这是一个在同一文档上使用两个组件的简单示例。我不确定这是否是正确的方法。这是 description-component html 文件中的内容:

<p>{{title}}</p>

我尝试使用 ractive-load.js 并为每个 list-component 文件加载 description-component html 就像在他们的 github 上的这个例子一样:

Ractive.load({
  Foo: 'my-components/foo.html',
  Bar: 'my-components/bar.html'
}).then( function ( components ) {
  var foo = new components.Foo({
    el: 'body',
    data: { ... }
  });

  var bar = new components.Bar({
    el: 'body',
    data: { ... }
  });
}).catch( handleError );

这似乎有点矫枉过正,我认为一定有更好的方法。我将如何着手解决这个问题?

Ractive 组件的加载与处理嵌套组件和将产生的内容传递给组件没有直接关系。

Ractive.load 通过获取一个或多个 html 文件然后将其解析为组件来工作。从您的代码示例来看,您似乎已经完成了该部分的工作。对于较大的应用程序,我通常使用构建工具插件来 pre-bundle 我所有的 Ractive 组件,这样它们就可以在一个文件中交付,甚至可以整合到我的主包 js 中。

无论组件如何可用,它们都需要在使用组件(或视图 parent)或全局注册:

Ractive.load({
  Foo: 'my-components/foo.html',
  Bar: 'my-components/bar.html'
}).then( function ( components ) {
  Ractive.components.foo = components.Foo;
  Ractive.components.bar = components.Bar;

  // now create your actual top-level view instance(s)

}).catch( handleError );

在组件架构中,您可以创建组件树或灌木丛。我通常只有一个顶级 app 组件,但创建多棵从 DOM.

中不同位置开始的树当然是可行的

为简单起见,继续上面的例子,让我们创建一个通用的 ractive 实例,它使用我们注册的两个组件 Foo 和 Bar(注意我们使用分配给 Ractive.components 的 属性 名称) :

const ractive = new Ractive({
    el: document.body,
    sayHello() {
        alert('hello from main Ractive instance');
    },
    template: `
        <h1>my kewl app</h1>
        <foo>
            <h3 on-click="sayHello()">hello world</h3>
            <bar bizz="{{buzz}}"></bar>
        </foo>
    `
});

在这种情况下,我们将一些内容(html 和我们的 bar 组件)传递给 foo 组件,方法是将其作为 <foo> 元素内容包含在内。

如何使用此内容取决于 foo 模板。有两种选择:

<div>
    <h2>foo component template</h2>
    {{>content}}
    <p>some more stuff</p>
</div>

在此示例中,我们使用 built-in 部分 "content" 告诉模板将提供的内容放入 {{>content}} 槽中。在这种情况下,提供的内容像部分内容一样传递,任何指令都将应用于 foo 组件。所以在这个例子中,点击 h3 header 会尝试 运行 foo.sayHello()。当将 bizz 数据传递给 bar 组件时,Ractive 将开始在 foo 组件中查找 buzz.

通常,这不是您想要的。您更希望 parent 拥有这些指令。所以 foo 模板看起来像:

<div>
    <h2>foo component template</h2>
    {{yield}}
    <p>some more stuff</p>
</div>

现在,当 h3 被点击时,它会调用主要的 ractive.sayHello() 方法,因为内容被传递给 foo 组件在 DOM 中呈现,但它是仍然由路过的实例拥有。同样,Ractive 将开始在主实例中寻找 buzz,而不是 foo.

使用 yield 您还可以命名要传递的多个部分:

<!-- "foo" template: -->
<div>
    <header>{{yield header}}</header>
    <section>
        <div>something here</div>
        <div>{{yield message}}</div>
    </section>
</div>

<!-- using "foo": -->
<div>
    <foo>
        {{#partial header}}
            <h2>This is the header to use</h2>
        {{/partial}}
        {{#partial message}}
            <p>This is the message to use, with a bar component to boot</p>
            <bar></bar>
        {{/partial}}
    </foo>
</div>