Wie man partielle Ansichten richtig rendert und JavaScript-Dateien in AJAX mit Express / Jade lädt?

Zusammenfassung

Ich bin mit Express + Jade für meine web-Anwendung, und ich habe Mühe mit der Darstellung teilweise den Blick für meine AJAX-navigation.

Ich habe zwei verschiedene Fragen, aber Sie sind Total miteinander verknüpft, so dass ich Sie in der gleichen post.
Ich denke, es wird ein langer post, aber ich garantiere, es ist interessant, wenn Sie bereits kämpfen mit den gleichen Problemen. Ich würde es sehr schätzen, wenn sich jemand die Zeit genommen, zu Lesen & eine Lösung vorschlagen.

TL;DR : 2 Fragen

  • Was ist der saubersten und Schnellste Weise zu erbringen Fragmente von Ansichten für eine AJAX-navigation mit Express + Jade ?
  • Wie sollte die JavaScript-Dateien relativ zu jeder Ansicht, die geladen werden ?

Anforderungen

  • Meine Web-App muss kompatibel sein mit Benutzer deaktiviert

    JavaScript
  • Wenn JavaScript aktiviert ist, wird nur die Seite die eigenen Inhalte (und nicht die
    gesamte layout) gesendet werden sollen, die vom server an den client
  • Die app muss schnell sein, und laden so wenig bytes wie möglich

Problem #1 : was ich versucht habe

Lösung 1 : haben unterschiedliche Dateien für die AJAX - & non-AJAX-Anfragen

Meine layout.jade ist :

doctype html
    html(lang="fr")
        head
            //Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            //Shared JS files go here
            script(src="js/jquery.min.js")

Meine page_full.jade ist :

extends layout.jade

block content
    h1 Hey Welcome !

Meine page_ajax ist :

h1 Hey Welcome

Und schließlich in router.js (Express) :

app.get("/page",function(req,res,next){
   if (req.xhr) res.render("page_ajax.jade");
   else res.render("page_full.jade");
});

Nachteile :

  • Wie Sie wahrscheinlich schon erraten, ich habe zum Bearbeiten meiner Ansichten, zweimal, jedes mal, wenn ich
    Notwendigkeit, etwas zu ändern. Ziemlich frustrierend sein.

Lösung 2 : gleiche Technik, mit `include`

Meine layout.jade bleibt unverändert :

doctype html
    html(lang="fr")
        head
            //Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            //Shared JS files go here
            script(src="js/jquery.min.js")

Meine page_full.jade ist jetzt :

extends layout.jade

block content
   include page.jade

Meine Seite.jade enthält den eigentlichen Inhalt ohne layout/block/erweitern/include :

h1 Hey Welcome

Habe ich jetzt in router.js (Express) :

app.get("/page",function(req,res,next){
   if (req.xhr) res.render("page.jade");
   else res.render("page_full.jade");
});

Vorteile :

  • Jetzt meine Inhalte nur einmal definiert, so ist besser.

Nachteile :

  • Ich noch zwei Dateien für eine Seite.
  • Ich habe mit der gleichen Technik in Express auf jeder route. Ich
    gerade zog mein code-Wiederholung-problem aus dem Jade-Express. Snap.

Lösung 3 : wie Lösung 2 aber die Befestigung der code-Wiederholung problem.

Mit Alex Ford-Technikdie ich definieren konnte, meine eigenen render Funktion in middleware.js :

app.use(function (req, res, next) {  
    res.renderView = function (viewName, opts) {
        res.render(viewName + req.xhr ? null : '_full', opts);
        next();
    };
 });

Und ändern Sie dann router.js (Express):

app.get("/page",function(req,res,next){
    res.renderView("/page");
});

wobei die anderen Dateien unverändert.

Vorteile

  • Es gelöst der code Wiederholung problem

Nachteile

  • Ich noch zwei Dateien für eine Seite.
  • Die Definition meiner eigenen renderView Methode fühlt sich etwas schmutzig. Nachdem alle, ich
    erwarte, dass meine template-engine/framework, um diese zu bewältigen für mich.

Lösung 4 : Verschieben der Logik Jade

Mag ich nicht mit zwei Dateien für eine Seite, so was ist, wenn ich ließ Jade sich entscheiden, was zu Rendern, anstatt Express ? Auf den ersten Blick scheint es sehr unangenehm für mich, weil ich denke, dass die template-engine nicht behandeln jede Logik überhaupt. Aber lassen Sie uns versuchen.

Zuerst muss ich übergeben Sie eine variable, um Jade, wird es sagen, welche Art von Anfrage es ist :

In middleware.js (Express)

app.use(function (req, res, next) {  
    res.locals.xhr = req.xhr;
 });

So, jetzt meine layout.jade wäre die gleiche wie zuvor :

doctype html
    html(lang="fr")
        head
            //Shared CSS files go here
            link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
        body
            div#main_content
                block content
            //Shared JS files go here
            script(src="js/jquery.min.js")

Und meine Seite.jade wäre :

if (!locals.xhr)
    extends layout.jade

block content
   h1 Hey Welcome !

Klasse, oder ? Außer, dass wird nicht funktionieren, weil bedingte erstreckt sind unmöglich in Jade. Also ich konnte das testen von Seite.jade zu layout.jade :

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               //Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                //Shared JS files go here
                script(src="js/jquery.min.js")
 else
     block content

und Seite.jade zurück zu :

extends layout.jade

block content
   h1 Hey Welcome !

Vorteile :

  • Jetzt habe ich nur eine Datei pro Seite
  • Ich nicht wiederholen Sie den req.xhr test in jeder route oder in jedem
    Ansicht

Nachteile :

  • Es ist die Logik in meinem template. Nicht gut

Zusammenfassung

Diese sind alle Techniken, die ich gedacht und ausprobiert, aber keine davon hat mich wirklich überzeugt. Mache ich etwas falsch ? Gibt es Reiniger Techniken ? Oder sollte ich eine andere template-engine/framework ?


Problem #2

Was passiert (mit einer dieser Lösungen), wenn eine Ansicht hat Ihre eigene JavaScript-Dateien ?

Zum Beispiel mit Lösung #4, wenn ich zwei Seiten, page_a.jade und page_b.jadedie beide Ihre eigenen client-side JavaScript-Dateien js/page_a.js und js/page_b.jswas Ihnen geschieht, wenn die Seiten geladen sind, in AJAX ?

Erste, die ich brauche, um zu definieren, eine extraJS block in layout.jade :

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               //Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                //Shared JS files go here
                script(src="js/jquery.min.js")
                //Specific JS files go there
                block extraJS
 else
     block content
     //Specific JS files go there
     block extraJS

dann page_a.jade wäre :

extends layout.jade

block content
   h1 Hey Welcome !
block extraJS
   script(src="js/page_a.js")

Wenn ich getippt localhost/page_a in meine URL-Leiste (non-AJAX-request)ich würde eine kompilierte version von :

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
            body
               div#main_content
                  h1 Hey Welcome A !
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

Sieht gut aus. Aber was würde passieren, wenn ich ging jetzt page_b mit meinem AJAX-navigation ? Meine Seite wäre eine kompilierte version von :

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                  h1 Hey Welcome B !
                  script(src="js/page_b.js")
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

js/page_a.js und js/page_b.js sind beide geladen, auf der gleichen Seite. Was passiert, wenn es einen Konflikt gibt (gleichen Variablen-Namen, etc...) ?
Plus, wenn ich zurück zu localhost/page_a mit AJAX, ich hätte dieses :

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                  h1 Hey Welcome B !
                  script(src="js/page_a.js")
               script(src="js/jquery.min.js")
               script(src="js/page_a.js")

Den gleichen JavaScript-Datei (page_a.js) geladen ist zweimal auf der gleichen Seite ! Wird es dazu führen, dass Konflikte, Doppel-Entlassung von jedem Ereignis ?
Ob oder nicht, das ist der Fall, ich glaube nicht, dass es sauberen code.

So dass man sagen könnte, dass bestimmte JS-Dateien sollte in meinem block content so, dass Sie entfernt, wenn ich auf wechseln zu einer anderen Seite. So, meine layout.jade werden sollte :

if (!locals.xhr)
    doctype html
       html(lang="fr")
           head
               //Shared CSS files go here
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
           body
               div#main_content
                    block content
                    block extraJS
                //Shared JS files go here
                script(src="js/jquery.min.js")
 else
     block content
     //Specific JS files go there
     block extraJS

Recht ? Err....Wenn ich mich localhost/page_abekomme ich eine kompilierte version von :

doctype html
       html(lang="fr")
           head
               link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
            body
               div#main_content
                  h1 Hey Welcome A !
                  script(src="js/page_a.js")
               script(src="js/jquery.min.js")

Wie Sie vielleicht bemerkt haben, js/page_a.js ist tatsächlich geladen vor jQuery, so wird es nicht funktionieren, denn jQuery ist noch nicht definiert...
Also ich weiß nicht, was zu tun für dieses problem. Ich dachte, der Umgang mit Skript-Anfragen der client-Seite verwenden (Beispiel) jQuery.getScript(), aber der Kunde möchte wissen, welche Skripte' mit dem Namen, sehen Sie, wenn Sie schon geladen, vielleicht entfernen Sie Sie. Ich glaube nicht, dass es getan werden sollte-client-Seite.

Wie soll ich das machen JavaScript Dateien geladen via AJAX ? Server-Seite mit einer anderen Strategie/template-engine ? Client-Seite ?

Wenn Sie es bis hierher geschafft haben, du bist ein echter held, und ich bin dankbar, aber ich wäre noch dankbar, wenn Sie könnten mir einige Ratschläge geben 🙂

InformationsquelleAutor der Frage Waldo Jeffers | 2014-08-05

Schreibe einen Kommentar