2012-05-08 15 views
7

Ich versuche eine D3.js Visualisierung in eine Meteor App zu integrieren. Nachdem die Seite geladen wurde, fügt eine D3-Funktion basierend auf den verfügbaren Daten DOM-Elemente in eine <div> in meiner Vorlage ein.Verhindern, dass Vorlagen DOM-Elemente verwerfen

Immer wenn irgendwo auf der Seite ein reaktives Update ist, speichert Meteor den Inhalt der Vorlage, die von meiner D3.js-Funktion injiziert wurde. Ich kann die Elemente wieder einfügen, aber das führt zu einem unerwünschten Flimmern und einer Leistungsminderung.

Haben Sie eine Idee, wie Sie dieses Herunterfallen extern injizierter Elemente unterdrücken können? Da diese Elemente ursprünglich nicht Teil des Templates waren, werden sie als Teil des Meteor-Cleanup-Prozesses verworfen.

+0

Wir müssen einen guten Weg hinzufügen, um programmatisch eingebettete Elemente zu erhalten. Das Problem ist, dass wenn eine Vorlage neu gerendert wird, sie ersetzt, was auch immer im DOM ist, mit was auch immer es gerendert wird - es weiß nicht, welche Elemente auf andere Weise hinzugefügt wurden. – dgreensp

+0

@dgreensp - das ist ein Feature, kein Fehler. ;) – AbigailW

Antwort

1

Mit der Einführung der Spark Templating-Engine in Version 0.4.0 haben sie die {{#constant}} Blockhelfer eingeführt, um dieses Problem zu beheben.

http://meteor.com/blog/2012/08/31/introducing-spark-a-new-live-page-update-engine

Ihre HTML-Vorlage sollte in etwa so aussehen ....

<template name="samplePageTemplate"> 
    <div id="samplePage" class="page"> 
     {{#constant}} 
     <div id="sampleGraph"></div> 
     {{/constant}} 
    </div> 
</template> 

Und das Javascript sollte wie folgt aussehen ...

Template.samplePageTemplate.destroyed = function() { 
    this.handle && this.handle.stop(); 
}; 
Template.samplePageTemplate.rendered = function() { 
    self.node = self.find("svg"); 
    if (!self.handle) { 
     self.handle = Meteor.autorun(function(){ 

      $('#sampleGraph').html(''); 
      renderChart(); 

     }); 
    }; 
}; 

function renderChart(){ 

    // lots of d3 chart specific stuff 

    var vis = d3.select("#sampleGraph").append("svg:svg") 
     .attr("width", window.innerWidth) 
     .attr("height", window.innerHeight) 
     .append("svg:g") 
     .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); 

    // more d3 chart specific stuff 

    }); 
}; 

Ich habe manchmal musste self.node anstelle von self.handle verwenden, aber ansonsten sollte es ziemlich geradlinig sein.

1

Haben Sie versucht, den D3 injizierten Elementen (oder mindestens einem Elternelement) eindeutige IDs zu geben? Aus dem Dokument (http://docs.meteor.com/#livehtml):

Stellen Sie einfach sicher, dass jedes Ihrer fokussierbaren Elemente entweder eine eindeutige ID hat oder einen Namen hat, der innerhalb des nächsten übergeordneten Elements eindeutig ist Das hat eine ID. Meteor behält diese Elemente auch dann bei, wenn ihre umgebende Vorlage neu gerendert wird, aktualisiert jedoch ihre untergeordneten Elemente und kopiert alle Attributänderungen.

+0

Ich stimme zu, dass die Dokumentation zu implizieren scheint, dass das Hinzufügen einer eindeutigen ID zu einem Element verhindern würde, dass sie gelöscht wird, aber dies scheint nicht der Fall zu sein. In meiner Anwendung hatte jedes eingefügte Element eine eindeutige ID, die jedoch bei einem reaktiven Update trotzdem entfernt wurde. –

Verwandte Themen