Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Meteor:每个模板是否有一个反应范围?_Meteor_Handlebars.js - Fatal编程技术网

Meteor:每个模板是否有一个反应范围?

Meteor:每个模板是否有一个反应范围?,meteor,handlebars.js,Meteor,Handlebars.js,我在同一页面的多个(任意多个)位置呈现相同的把手模板。在每个模板中,我需要一个按钮来切换div的可见性。当我使用Session.set保存此状态时,单击一个按钮显然会切换所有模板实例化中不需要的所有div 我可以将状态保存在模板实例的数据上下文中(该实例绑定到template.myTemplate.rendered和template.myTemplate.created回调中的this.data),但存在两个问题 this.data不是被动数据源,因此不会传播到div 我无权访问template

我在同一页面的多个(任意多个)位置呈现相同的把手模板。在每个模板中,我需要一个按钮来切换div的可见性。当我使用
Session.set
保存此状态时,单击一个按钮显然会切换所有模板实例化中不需要的所有div

我可以将状态保存在模板实例的数据上下文中(该实例绑定到
template.myTemplate.rendered
template.myTemplate.created
回调中的
this.data
),但存在两个问题

  • this.data
    不是被动数据源,因此不会传播到div
  • 我无权访问
    template.myTemplate.events
    中的模板实例(如上所述)
  • 最后,我可以将它保存到一个集合中。但是,如何唯一地标识呈现的每个模板的状态?jQuery也可能有一种黑客方式,但这不是我想要开发Meteor应用程序的方式,该应用程序应该与反应式模板一起工作。尤其是当模板变得更复杂时

    我是否遗漏了一些东西,或者对于每个模板实例化,是否真的没有类似于AngularJS的控制器通过
    $scope

    更新: 我在想这样的事情

    template.html:

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

    我认为关于流星核心的讨论已经过时(尽管是最近的)。(以下引用),这应该是可能的:

    Template.myTemplate.events({
       foo: function(event, template) {
          var _div = template.find('...');
       }
    });
    
    handler函数接收两个参数:event,一个包含事件信息的对象;template,一个定义处理程序的模板实例。根据处理事件的当前元素的上下文,处理程序还接收一些额外的上下文数据。在Handlebars模板中,元素的上下文是该元素所在的Handlebars数据上下文,由块帮助器(如#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);
        }
    });
    

    这就是我如何实现每个模板实例反应源的方法

    我只想问用户当恐龙的灭绝状态设置为灭绝时,恐龙灭绝的原因

    <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>
    
    我们监听用户何时更改熄灭状态选择,并更新
    新熄灭状态
    ,并在
    熄灭状态下调用
    已更改

    Template.dinosaur.events({
      'change [name="extinction-status"]': function(event, template) {
        var extinctStatus = $(event.target).val();
        template.data.newExtinctStatus = extinctStatus;
        template.data.extinctStatusDep.changed();
      }
    });
    
    在helper中,我们说我们依赖于
    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;
        }
      }
    });
    

    添加到
    此.data
    有点像黑客,但它允许每个模板的反应性,在依赖尚未保存到
    集合中的数据时非常有用。

    更新的答案-METEOR 0.8.3

    Meteor现在提供了
    UI.\u templateInstance()
    函数,该函数允许在模板帮助程序中访问模板实例。这使得实现更加简洁:

    一,。 在下面的HTML代码中,删除
    {{#with templateInstanceId=getTemplateInstanceId}

    二,。 用以下代码替换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);
        };
    
    以前的答案 我在我的项目中也有同样的要求:唯一地标识一个模板实例,以便与
    Session.set一起使用

    下面是我的简单技巧,使用上下文替换和“滑动”唯一实例id(稍后将对此进行详细介绍):

    在客户端代码中的任意位置,放置:

    var templateInstanceId = 0;
    
    UI.registerHelper('getTemplateInstanceId', function()
    {
        return templateInstanceId++;
    });
    
    然后在要唯一标识实例的模板中使用
    {{#with templateInstanceId=getTemplateInstanceId}
    。以您的示例为例,可能是这样的(未经测试):

    HTML:

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


    这个id在每次模板渲染时都会更新,我没有找到其他方法。这意味着任何新的呈现都将使存储在会话中的唯一id无效。如果div包含反应式数据源,则会发生新的呈现。根据您的情况,这可能是个问题,也可能不是。所有其他答案都太复杂和/或过时。从Meteor 1.0开始,维护每个模板状态的建议解决方案是使用存储在:

    模板实例对象表示文档中模板的引用。它可以用来访问DOM,并且可以为其分配属性,这些属性会随着模板的反应性更新而保持不变。[…]您可以将自己选择的其他属性指定给对象

    反应变量由以下程序提供:

    一个ReactiveVar持有一个可以获取和设置的值,这样调用
    set
    将使调用
    get
    的任何计算无效,这与反应式数据源的通常约定是一致的

    您的代码变成:

    Template.jsonObject.onCreated=函数(){
    this.hidden=新的反应变量(false);
    };
    Template.jsonObject.helpers({
    隐藏:函数(){
    返回Template.instance().hidden.get()?“hidden”:“”;
    }
    });
    Template.jsonObject.events({
    “单击输入”:函数(事件、模板){
    template.hidden.set(true);
    }
    });
    
    HTML与您预期的相同:

    
    点击我
    隐藏是{{Hidden}


    谢谢,但这仍然存在一个问题,即template.data不是被动的。对。这是有道理的。我更新了我的答案。这可能有点黑客。加上一个黑客解决方案:)我想如果我有一个全局计数器来生成它工作的ID,.下划线有一个漂亮的
    。.uniqueId
    函数,可能很有用。有一个.聪明的。我将其简化为动画系统,但您所建议的核心工作得非常好,即将依赖项作为this.data.Great问题的属性。我在AngularJS中缺少此功能。从Meteor 0.9.1开始,
    UI.\u templateInstance
    已重命名为
    Template.instance
    。事情是这样的
    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);
        };
    
    var templateInstanceId = 0;
    
    UI.registerHelper('getTemplateInstanceId', function()
    {
        return templateInstanceId++;
    });
    
    <!-- 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>
    
    Template.divWithToggleButton.events(
    {
        'click button': function(event, template) 
        {
            Session.set("visible", this.templateInstanceId);
        },
    });
    
    Template.divWithToggleButton.visible= function() 
    { 
        return Session.equals("visible", this.templateInstanceId);
    };