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
如何在meteorjs中保留(状态)非反应性DOM元素?_Meteor_Meteor Blaze - Fatal编程技术网

如何在meteorjs中保留(状态)非反应性DOM元素?

如何在meteorjs中保留(状态)非反应性DOM元素?,meteor,meteor-blaze,Meteor,Meteor Blaze,我试图理解在Meteor模板中使用有状态/非反应性DOM组件的选项,以允许组件在Meteor更新DOM时保持其状态 其中一个具体的例子涉及到lapper.js:我有一个包含Leaftlet地图的应用程序,我希望用户能够在地图显示和其他内容之间切换。地图是交互式的——用户可以在地图上平移和缩放——如果用户从地图切换到其他内容,然后返回地图,我希望地图的当前缩放/平移状态能够保留 我的第一次尝试是将地图放在一个模板中,将其他内容放在另一个模板中,并在包含的模板中使用条件逻辑来确定渲染哪个模板: HT

我试图理解在Meteor模板中使用有状态/非反应性DOM组件的选项,以允许组件在Meteor更新DOM时保持其状态

其中一个具体的例子涉及到lapper.js:我有一个包含Leaftlet地图的应用程序,我希望用户能够在地图显示和其他内容之间切换。地图是交互式的——用户可以在地图上平移和缩放——如果用户从地图切换到其他内容,然后返回地图,我希望地图的当前缩放/平移状态能够保留

我的第一次尝试是将地图放在一个模板中,将其他内容放在另一个模板中,并在包含的模板中使用条件逻辑来确定渲染哪个模板:

HTML:

<body>
  <div>
    <input type="submit" id="mapbutton" value="Display Map">
    <input type="submit" id="otherbutton" value="Display Other Stuff">
  </div>
  {{#if showmap}}
    {{> map}}
  {{else}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="map">
  <div id="map"></div>
</template>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.map.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
<body>
  <div>
    <input type="submit" id="mapbutton" value="Map">
    <input type="submit" id="otherbutton" value="Other Stuff">
  </div>
  <div id="map" class="{{#if showmap}}visible{{else}}hidden{{/if}}"></div>
  {{#if showother}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.body.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    },
    "showother" : function() { 
        return !Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
#map.visible {
  display: block;
}

#map.hidden {
  display: none;
}
<body>                                                                                                      
  <div>                                                                                                     
    <input type="submit" id="mapbutton" value="Map">                                                        
    <input type="submit" id="otherbutton" value="Other Stuff">                                              
  </div>                                                                                                    
  {{#if showmap}}                                                                                           
    {{> map}}                                                                                               
  {{else}}                                                                                                  
    {{> otherstuff}}                                                                                        
  {{/if}}                                                                                                   
</body>                                                                                                     

<template name="map">                                                                                       
  <div id="mapcontainer">                                                                                   
    <div id="map"></div>                                                                                    
  </div>                                                                                                    
</template>                                                                                                 

<template name="otherstuff">                                                                                
  <p>Here is some other stuff</p>                                                                           
</template> 
var $mapdiv = undefined;                                                                                    
Template.map.rendered = function() {                                                                        
    if ($mapdiv === undefined) {                                                                            
        // if this is the first time the map has been rendered, create it                                   
        var map = L.map('map', {                                                                            
            doubleClickZoom: false                                                                          
        }).setView([38.0, -98.0], 5);                                                                       
        L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {                               
            maxZoom: 18,                                                                                    
            id: 'examples.map-i875mjb7'                                                                     
        }).addTo(map);                                                                                      
        // and hang on to the map's div element for re-use later                                            
        $mapdiv = $("#map");                                                                                
    } else {                                                                                                
        // map has already been created, so just empty out the container                                    
        // and re-insert it                                                                                 
        $("#mapcontainer").empty();                                                                         
        $("#mapcontainer").append($mapdiv);                                                                 
    }                                                                                                       
};                                                                                                          

Session.setDefault("showmap", true);                                                                        

Template.body.helpers({                                                                                     
    "showmap" : function() {                                                                                
        return Session.get("showmap");                                                                      
    }                                                                                                       
});                                                                                                         

Template.body.events({                                                                                      
    "click input#mapbutton": function() {                                                                   
        Session.set("showmap", true);                                                                       
    },                                                                                                      
    "click input#otherbutton": function() {                                                                 
        Session.set("showmap", false);                                                                      
    }                                                                                                       
});                                                                                                         
这种方法的问题是,每次用户切换到地图显示时,Meteor都会重新渲染地图模板,创建一个新的传单地图(以及相关的DOM组件),该地图从头开始初始化。这意味着用户以前在地图中所做的任何平移和/或缩放设置都将丢失。在制作传单地图时,还需要短暂的延迟。我希望传单地图只在第一次显示时创建一次,然后在用户切换到其他内容时保存在屏幕外的某个位置,以便以后可以立即切换回,而不会引起构建延迟,并保留其以前的平移/缩放状态

我知道实现这一点的一种方法是设计HTML模板,在切换显示时将map div保留在DOM中, 并在必要时使用CSS将其隐藏。如下所示:

HTML:

<body>
  <div>
    <input type="submit" id="mapbutton" value="Display Map">
    <input type="submit" id="otherbutton" value="Display Other Stuff">
  </div>
  {{#if showmap}}
    {{> map}}
  {{else}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="map">
  <div id="map"></div>
</template>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.map.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
<body>
  <div>
    <input type="submit" id="mapbutton" value="Map">
    <input type="submit" id="otherbutton" value="Other Stuff">
  </div>
  <div id="map" class="{{#if showmap}}visible{{else}}hidden{{/if}}"></div>
  {{#if showother}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.body.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    },
    "showother" : function() { 
        return !Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
#map.visible {
  display: block;
}

#map.hidden {
  display: none;
}
<body>                                                                                                      
  <div>                                                                                                     
    <input type="submit" id="mapbutton" value="Map">                                                        
    <input type="submit" id="otherbutton" value="Other Stuff">                                              
  </div>                                                                                                    
  {{#if showmap}}                                                                                           
    {{> map}}                                                                                               
  {{else}}                                                                                                  
    {{> otherstuff}}                                                                                        
  {{/if}}                                                                                                   
</body>                                                                                                     

<template name="map">                                                                                       
  <div id="mapcontainer">                                                                                   
    <div id="map"></div>                                                                                    
  </div>                                                                                                    
</template>                                                                                                 

<template name="otherstuff">                                                                                
  <p>Here is some other stuff</p>                                                                           
</template> 
var $mapdiv = undefined;                                                                                    
Template.map.rendered = function() {                                                                        
    if ($mapdiv === undefined) {                                                                            
        // if this is the first time the map has been rendered, create it                                   
        var map = L.map('map', {                                                                            
            doubleClickZoom: false                                                                          
        }).setView([38.0, -98.0], 5);                                                                       
        L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {                               
            maxZoom: 18,                                                                                    
            id: 'examples.map-i875mjb7'                                                                     
        }).addTo(map);                                                                                      
        // and hang on to the map's div element for re-use later                                            
        $mapdiv = $("#map");                                                                                
    } else {                                                                                                
        // map has already been created, so just empty out the container                                    
        // and re-insert it                                                                                 
        $("#mapcontainer").empty();                                                                         
        $("#mapcontainer").append($mapdiv);                                                                 
    }                                                                                                       
};                                                                                                          

Session.setDefault("showmap", true);                                                                        

Template.body.helpers({                                                                                     
    "showmap" : function() {                                                                                
        return Session.get("showmap");                                                                      
    }                                                                                                       
});                                                                                                         

Template.body.events({                                                                                      
    "click input#mapbutton": function() {                                                                   
        Session.set("showmap", true);                                                                       
    },                                                                                                      
    "click input#otherbutton": function() {                                                                 
        Session.set("showmap", false);                                                                      
    }                                                                                                       
});                                                                                                         
CSS:

<body>
  <div>
    <input type="submit" id="mapbutton" value="Display Map">
    <input type="submit" id="otherbutton" value="Display Other Stuff">
  </div>
  {{#if showmap}}
    {{> map}}
  {{else}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="map">
  <div id="map"></div>
</template>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.map.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
<body>
  <div>
    <input type="submit" id="mapbutton" value="Map">
    <input type="submit" id="otherbutton" value="Other Stuff">
  </div>
  <div id="map" class="{{#if showmap}}visible{{else}}hidden{{/if}}"></div>
  {{#if showother}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.body.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    },
    "showother" : function() { 
        return !Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
#map.visible {
  display: block;
}

#map.hidden {
  display: none;
}
<body>                                                                                                      
  <div>                                                                                                     
    <input type="submit" id="mapbutton" value="Map">                                                        
    <input type="submit" id="otherbutton" value="Other Stuff">                                              
  </div>                                                                                                    
  {{#if showmap}}                                                                                           
    {{> map}}                                                                                               
  {{else}}                                                                                                  
    {{> otherstuff}}                                                                                        
  {{/if}}                                                                                                   
</body>                                                                                                     

<template name="map">                                                                                       
  <div id="mapcontainer">                                                                                   
    <div id="map"></div>                                                                                    
  </div>                                                                                                    
</template>                                                                                                 

<template name="otherstuff">                                                                                
  <p>Here is some other stuff</p>                                                                           
</template> 
var $mapdiv = undefined;                                                                                    
Template.map.rendered = function() {                                                                        
    if ($mapdiv === undefined) {                                                                            
        // if this is the first time the map has been rendered, create it                                   
        var map = L.map('map', {                                                                            
            doubleClickZoom: false                                                                          
        }).setView([38.0, -98.0], 5);                                                                       
        L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {                               
            maxZoom: 18,                                                                                    
            id: 'examples.map-i875mjb7'                                                                     
        }).addTo(map);                                                                                      
        // and hang on to the map's div element for re-use later                                            
        $mapdiv = $("#map");                                                                                
    } else {                                                                                                
        // map has already been created, so just empty out the container                                    
        // and re-insert it                                                                                 
        $("#mapcontainer").empty();                                                                         
        $("#mapcontainer").append($mapdiv);                                                                 
    }                                                                                                       
};                                                                                                          

Session.setDefault("showmap", true);                                                                        

Template.body.helpers({                                                                                     
    "showmap" : function() {                                                                                
        return Session.get("showmap");                                                                      
    }                                                                                                       
});                                                                                                         

Template.body.events({                                                                                      
    "click input#mapbutton": function() {                                                                   
        Session.set("showmap", true);                                                                       
    },                                                                                                      
    "click input#otherbutton": function() {                                                                 
        Session.set("showmap", false);                                                                      
    }                                                                                                       
});                                                                                                         
对于这个简单的示例,这很好,但实际上我的应用程序(以及关联的模板和生成的DOM)要复杂得多。 我真正想要的是能够在DOM中任意移动贴图组件。例如,根据上下文的不同 映射可能出现在一个表中,或者全屏显示,或者根本不显示,我希望在所有这些上下文之间保留映射的内部状态。为地图使用Meteor模板,并使用条件逻辑确定其包含位置,这似乎是构建此类内容的自然方式,但这又回到了上述问题,即每次渲染地图模板时,都会从中重建地图 划伤并重置为初始状态

有没有一种方法可以让Meteor“缓存”其对特定模板的呈现,并保留关联的DOM元素,以便以后在呈现其他内容时使用该模板时,使用先前构造的DOM元素?我意识到这违背了反应式方法的本质,但在这种情况下,我正试图使用一个复杂的非反应式组件,而且似乎支持这些东西在许多情况下都是有用的

顺便说一句,这个问题不是Leaftlet.js特有的。我还想在Meteor应用程序中使用其他非反应性、有状态的组件,我希望找到一种优雅的方法来解决所有这些组件的问题

有人知道有没有办法做到这一点,或者有没有更好的方法


谢谢

我认为,除非使用CSS,否则在不进行任何重新渲染的情况下,无法将渲染的项目保持为隐藏/显示状态

Blaze(负责渲染模板的组件)还不能做到这一点。看看这个主题,他们基本上说的是相同的,但它来自一个meteor dev:


要么依赖CSS,要么将所需的值保存在反应式词典中,并在渲染地图模板时使用它们。

谢谢@Billybobbonne。您的注释保留了所需的值,并在呈现模板时重复使用这些值,这让我想到尝试以下方法:

HTML:

<body>
  <div>
    <input type="submit" id="mapbutton" value="Display Map">
    <input type="submit" id="otherbutton" value="Display Other Stuff">
  </div>
  {{#if showmap}}
    {{> map}}
  {{else}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="map">
  <div id="map"></div>
</template>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.map.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
<body>
  <div>
    <input type="submit" id="mapbutton" value="Map">
    <input type="submit" id="otherbutton" value="Other Stuff">
  </div>
  <div id="map" class="{{#if showmap}}visible{{else}}hidden{{/if}}"></div>
  {{#if showother}}
    {{> otherstuff}}
  {{/if}}
</body>

<template name="otherstuff">
  <p>Here is some other stuff</p>
</template>
Template.body.rendered = function() {
    var map = L.map('map', {
        doubleClickZoom: false
    }).setView([38.0, -98.0], 5);

    L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
        maxZoom: 18,
        id: 'examples.map-i875mjb7'
    }).addTo(map);
};

Session.setDefault("showmap", true);

Template.body.helpers({
    "showmap" : function() { 
        return Session.get("showmap");
    },
    "showother" : function() { 
        return !Session.get("showmap");
    }
});

Template.body.events({
    "click input#mapbutton": function() {
        Session.set("showmap", true);
    },
    "click input#otherbutton": function() {
        Session.set("showmap", false);
    }
});
#map.visible {
  display: block;
}

#map.hidden {
  display: none;
}
<body>                                                                                                      
  <div>                                                                                                     
    <input type="submit" id="mapbutton" value="Map">                                                        
    <input type="submit" id="otherbutton" value="Other Stuff">                                              
  </div>                                                                                                    
  {{#if showmap}}                                                                                           
    {{> map}}                                                                                               
  {{else}}                                                                                                  
    {{> otherstuff}}                                                                                        
  {{/if}}                                                                                                   
</body>                                                                                                     

<template name="map">                                                                                       
  <div id="mapcontainer">                                                                                   
    <div id="map"></div>                                                                                    
  </div>                                                                                                    
</template>                                                                                                 

<template name="otherstuff">                                                                                
  <p>Here is some other stuff</p>                                                                           
</template> 
var $mapdiv = undefined;                                                                                    
Template.map.rendered = function() {                                                                        
    if ($mapdiv === undefined) {                                                                            
        // if this is the first time the map has been rendered, create it                                   
        var map = L.map('map', {                                                                            
            doubleClickZoom: false                                                                          
        }).setView([38.0, -98.0], 5);                                                                       
        L.tileLayer('https://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {                               
            maxZoom: 18,                                                                                    
            id: 'examples.map-i875mjb7'                                                                     
        }).addTo(map);                                                                                      
        // and hang on to the map's div element for re-use later                                            
        $mapdiv = $("#map");                                                                                
    } else {                                                                                                
        // map has already been created, so just empty out the container                                    
        // and re-insert it                                                                                 
        $("#mapcontainer").empty();                                                                         
        $("#mapcontainer").append($mapdiv);                                                                 
    }                                                                                                       
};                                                                                                          

Session.setDefault("showmap", true);                                                                        

Template.body.helpers({                                                                                     
    "showmap" : function() {                                                                                
        return Session.get("showmap");                                                                      
    }                                                                                                       
});                                                                                                         

Template.body.events({                                                                                      
    "click input#mapbutton": function() {                                                                   
        Session.set("showmap", true);                                                                       
    },                                                                                                      
    "click input#otherbutton": function() {                                                                 
        Session.set("showmap", false);                                                                      
    }                                                                                                       
});                                                                                                         

这似乎很有效。这感觉有点笨拙,但我喜欢这样一个事实:它让我把地图放在一个模板中,我可以在任何地方使用,就像任何其他模板一样,但地图只创建了一次。

我很高兴你找到了一个令人满意的方法来完成事情。但是,由于您提到可能需要在多个上下文中显示多个映射,我建议您使用反应式词典而不是
会话
var。例如,您可以使用
random.id
存储每个映射标志,并将其附加到
rendered
函数(
this.id=random.id()
)中。这样,您可以根据需要使用任意多个
showmap
标志。使用反应式字典
map
设置它的一个例子是
map.set(this.id,true)