Meteor: Is there a reactive per-template scope?

2019-07-19 13:40发布

我在呈现在同一页面上的多个(任意多个)位置相同的把手模板。 每个模板里面,我想有一个按钮来切换一个div的可见性。 当我保存这个状态Session.set ,点击一个按钮,显然在切换这是不希望在所有模板实例所有的div。

我可以保存状态在模板实例(这势必会的数据上下文this.dataTemplate.myTemplate.renderedTemplate.myTemplate.created回调),但有两个问题这一点。

  1. this.data不是反应性的数据源,因此将不会传播到div
  2. 我没有访问模板实例中Template.myTemplate.events (作为讨论的流星核 )

最后,我可以以某种方式将其保存到一个集合。 但是,如何将我唯一识别每个模板的状态呈现? 也可能存在与jQuery一个哈克的方式,但是这不是我想发展,都应该有反应的模板工作流星应用程序的方式。 尤其是,当模板变得更加复杂。

我缺少的东西还是真的没有等同于AngularJS的控制器,获得通过一个$scope为每个模板实例?

更新 :我在想这样的事情。

template.html:

<template name="jsonObject">
    <input type="button" />
    <div class="{{hidden}}">content</div>
</template>

client.js:

Template.jsonObject.hidden = function(){
    var ret = "";
    if (this._hidden) {
        ret = "hidden";
    }
    return ret;
};

Template.jsonObject.events({
    'click input' : function(event, template){
        template.data._hidden = true;
    }
});

Answer 1:

所有其他的答案太复杂和/或过时。 由于流星1.0,推荐的解决方案,以维持每个模板状态是使用反应性变量存储在模板实例 :

模板实例对象表示文档中的模板的发生。 它可用于访问DOM,它可以被分配作为坚持模板被动更新的属性。 [...]你可以指定你的选择对象的附加属性。

反应变量由提供reactive-var芯包 :

甲ReactiveVar认为可以得到和设置,使得主叫的单个值set会作废调用任何计算中get ,根据用于反应性数据源的通常的合同。

您的代码变为:

Template.jsonObject.onCreated = function () {
  this.hidden = new ReactiveVar(false);
};

Template.jsonObject.helpers({
  hidden: function () {
    return Template.instance().hidden.get() ? 'hidden' : '';
  }
});

Template.jsonObject.events({
  'click input': function (event, template) {
    template.hidden.set(true);
  }
});

该HTML是你所期望的一样:

<template name="jsonObject">
  <button>Click Me</button>
  <p>Hidden is {{hidden}}.</p>
</template>


Answer 2:

这是我实现了每个模板实例反应源

我只希望当它灭绝的状态设置为灭绝,要求用户原因了恐龙的灭绝。

<template name="dinosaur">
   <label for="extinction-status">Extinction status</label>
   <select name="extinction-status">
     <option value="not-extinct">Not extinct</option>
     <option value="extinct">Extinct</option>
   </select>
   {{#if isExtinct extinctStatus newExtinctStatus extinctStatusDep}}
   <label for="extinction-reason">Reason for extinction</label>
   <input name="extinction-reason" type="text" placeholder="Why is it extinct?"/>
   {{/if}}
</template>

反应性地显示的原因领域,我们一加Deps.Dependencythis.data模板created功能

Template.dinosaur.created = function() {
  this.data.newExtinctStatus = null;
  this.data.extinctStatusDep = new Deps.Dependency;
};

我们听当用户改变灭绝状态选择的,并更新newExtinctStatus ,并呼吁changed我们的extinctStatusDep

Template.dinosaur.events({
  'change [name="extinction-status"]': function(event, template) {
    var extinctStatus = $(event.target).val();
    template.data.newExtinctStatus = extinctStatus;
    template.data.extinctStatusDep.changed();
  }
});

在我们说的帮手,我们依赖于Deps.Dependency我们传递

Template.dinosaur.helpers({
  isExtinct: function(status, newStatus, statusDep) {
    if (statusDep) {
      statusDep.depend();
    }
    if (newStatus) {
      if (newStatus == 'extinct') {
        return true;
      }
    else if (status == 'extinct') {
        // No new status is set, so use the original.
        return true;
    }
  }
});

这是一个有点涉及增加一个黑客this.data ,但它允许每个模板反应,有用的,当你依靠,在一个尚未保存的东西数据Collection呢。



Answer 3:

已更新答案-流星0.8.3

流星现在提供UI._templateInstance()函数,它可以访问的模板实例模板助手。 这允许更简单地实施:

1.在下面的HTML代码,删除{{#with templateInstanceId=getTemplateInstanceId}}

2.由这一个替换JS代码:

var templateInstanceId = 0;

Template.divWithToggleButton.created= function() 
    { 
    this.templateInstanceId = ++templateInstanceId;
    };

Template.divWithToggleButton.events(
    {
    'click button': function(event, template) 
        {
        Session.set("visible", template.templateInstanceId);
        },
    });

Template.divWithToggleButton.visible= function() 
    { 
    return Session.equals("visible", UI._templateInstance().templateInstanceId);
    };

FORMER答案,我在我的项目有相同的要求:唯一标识用于使用模板实例Session.set

这是我简单的黑客,使用上下文替换和“滑动”唯一的实例ID(以后会更多):

任何地方的客户端代码,把:

var templateInstanceId = 0;

UI.registerHelper('getTemplateInstanceId', function()
{
    return templateInstanceId++;
});

然后使用{{#with templateInstanceId=getTemplateInstanceId }}在你想唯一标识实例的模板。 随着你的榜样,它可能是这样的(未测试):

HTML:

<!-- Div with a toggle visibility button. Use as a Block Helpers (with # instead of >) -->
<template name="divWithToggleButton">
    {{#with templateInstanceId=getTemplateInstanceId }}
    <div>
        <!-- The 'toggle visibility' button -->
        <button type="button">Toggle Visibility</button>

        <!-- The div content -->
        {{#if visible}}
            {{> UI.contentBlock}}
        {{/if}}
    </div>
    {{/with}}
</template>

JS(客户代码):

Template.divWithToggleButton.events(
{
    'click button': function(event, template) 
    {
        Session.set("visible", this.templateInstanceId);
    },
});

Template.divWithToggleButton.visible= function() 
{ 
    return Session.equals("visible", this.templateInstanceId);
};

现在关于这个奇怪的“滑动”唯一的实例ID:

此ID是在每个模板渲染更新,我发现没有其他的办法。 这意味着任何新的渲染会作废存储在会话的唯一ID。 如果你的div包含反应数据源发生新的渲染。 根据你的情况,这可能是一个问题或没有。



Answer 4:

我认为流星核的讨论已经过时了(虽然它是最新的)。 按照文档 (以下引用),这应该是可能的:

Template.myTemplate.events({
   foo: function(event, template) {
      var _div = template.find('...');
   }
});

该处理程序函数接收两个参数:事件,与关于事件的信息,和模板的对象,其中,该处理程序被定义该模板的模板实例。 处理程序还接收在这一些附加上下文数据,根据当前的元件处理事件的上下文中。 在一个把手模板,元素的上下文是该元件发生其由块助手如#with和#each设置把手数据上下文。

更新

假设每一个可隐藏的div有一个唯一的ID,如果你尝试过这样的事情是什么? 我没有测试它。

Template.jsonObject.hidden = function(){
    var _id = $(".classOfPossibleHiddenDiv").prop("id");
    return Session.get(_id) || false;
};

Template.jsonObject.events({
    'click input' : function(event, template){
        Session.set($(template.find(".classOfPossibleHiddenDiv")).prop("id"), true);
    }
});


文章来源: Meteor: Is there a reactive per-template scope?