Meteor Blaze 访问 Template.onCreated 内的 Template.contentBlock

Posted

技术标签:

【中文标题】Meteor Blaze 访问 Template.onCreated 内的 Template.contentBlock【英文标题】:Meteor Blaze access Template.contentBlock inside Template.onCreated 【发布时间】:2018-08-15 13:36:55 【问题描述】:

我正在编写一个带有孩子的自定义 Blaze 块助手:

<template name="parent">
    > Template.contentBlock ..
</template>

<template name="child">
    > Template.contentBlock ..
</template>

我的预期用例是有一个带有任意子节点的模板,我在 html 文件中定义。

#parent

  #child id="child1" title="Child 1"
    <p>This is content of child 1</p>
  /child

  #child id="child2" title="Child 2"
    <p>This is content of child 2</p>
  /child

  #child id="childN" title="Child N"
    <p>This is content of child N</p>
  /child

/parent

目前没有问题。但是,在父模板的onCreated / autorun 中,我想访问child 模板。我想使用这些数据在父模板元素中动态创建,基于

Template.parent.onCreated(function () 
    const instance = this;
    instance.state = new ReactiveDict();

    instance.autorun(function () 
        const contentBlocks = // how?
        instance.state.set("children", contentBlocks);
    );
);

Template.parent.helpers(
    children() 
        return Template.instance().state.get("children");
    
);

children 将在parent 模板中使用如下:

#parent

  #each children
    do something with this.value
  /each      

  #child id="child1" title="Child 1"
    <p>This is content of child 1</p>
  /child

  #child id="child2" title="Child 2"
    <p>This is content of child 2</p>
  /child

  #child id="childN" title="Child N"
    <p>This is content of child N</p>
  /child

/parent

我不想访问 contentBlock 的内容(&lt;p&gt;),而是获取添加的child 模板列表。

当前的 Template / Blaze API 可以实现吗? documentation 在这一点上有点薄。

基本上和这个帖子相反:How to get the parent template instance (of the current template)


编辑 1:使用父视图的渲染功能(仅部分工作)

我找到了一种方法来获取 parent 模板的孩子,但不是他们的 data 响应式:

// in Template.parant.onCreated -> autorun
const children = instance.view.templateContentBlock.renderFunction()
    .filter(child => typeof child === 'object')
    .map(el => Blaze.getData(el._render()));
console.log(children);
// null, null, null because Blaze.getData(view) does return null

我发现的另一种方法是使用共享的ReactiveVar,但在我看来两者都不够干净。我只想获取父级js代码中的Template实例列表。


编辑 2:使用共享的 ReactiveVar(仅部分工作)

可以使用共享的ReactiveVar,只要它在两个模板的范围内:

const _cache = new ReactiveVar();

Template.parent.onCreated(function () 
    const instance = this;
    instance.state = new ReactiveDict();

    instance.autorun(function () 
        const children = Object.values(_cache.get());
        instance.state.set("children", children);
    );
);

Template.parent.helpers(
    children() 
        return Template.instance().state.get("children");
    
);

工作(但只渲染一次,不响应):

Template.child.onCreated(function () 
    const instance = this;
    const data = Template.currentData();
    const cache = _cache.get();
    cache[data.id] = data;
    _cache.set(cache);
);

不工作(子自动运行正在设置值,但未呈现新值):

Template.child.onCreated(function () 
    const instance = this;
    instance.autorun(function() 
        const instance = this;
        const data = Template.currentData();
        const cache = _cache.get();
        cache[data.id] = data;
        _cache.set(cache);
    );
);

【问题讨论】:

【参考方案1】:

这就是我想出的。请让我知道这是您想要的还是我误解了。

main.html:

<body>
    > content
</body>

<template name="content">
    #parent

        #each children
            <p>do something with this.id</p>
            <p>data: this.tmpl.data.title</p>
        /each

        #child id="child1" title="Child 1" parentTemplate=this.parentTemplate
            <p>This is content of child 1</p>
        /child

        #child id="child2" title="Child 2" parentTemplate=this.parentTemplate 
            <p>This is content of child 2</p>
        /child

        #child id="childN" title="Child N" parentTemplate=this.parentTemplate 
            <p>This is content of child N</p>
        /child

    /parent
</template>

<template name="parent">
    > Template.contentBlock parentTemplate=template
</template>

<template name="child">
    > Template.contentBlock 
</template>

main.js

import  Template  from 'meteor/templating';
import  ReactiveVar  from 'meteor/reactive-var';

import './main.html';

Template.content.helpers(
    children() 
        return this.parentTemplate.children.get();
    ,
);

Template.parent.onCreated(function () 
    this.children = new ReactiveVar([]);
);

Template.parent.helpers(
    template() 
        return Template.instance();
    
);

Template.child.onRendered(function () 
    const children = this.data.parentTemplate.children.get();
    children.push( id: this.data.id, tmpl: this );
    this.data.parentTemplate.children.set(children);
);

输出:

虽然它使用ReactiveVar 并不理想,但它不依赖任何全局,您可以将代码放在不同的文件中,没问题。

【讨论】:

我检查了您的解决方案。它运行良好,在 .但它也引入了第三个模板实例。为了公平起见,我会等到赏金期的日子。

以上是关于Meteor Blaze 访问 Template.onCreated 内的 Template.contentBlock的主要内容,如果未能解决你的问题,请参考以下文章

Meteor + Blaze - If else 语句

Meteor/Blaze - 参数中的简单字符串连接

带有 Meteor 的 Blaze-Apollo,观察者不会触发变量更改的订阅

在 Meteor 的 onCreated 中获取模板变量

使用 Meteor 和 blaze 在掌上电脑上正确加载数据

Angular、React 和 Blaze(客户端 Meteor)之间的主要设计差异? [关闭]