web-dev-qa-db-fra.com

Node.js avec Express: importer du javascript côté client à l'aide de balises de script dans les vues Jade?

J'ai un serveur express node.js fonctionnant avec le moteur de modèle Jade.

J'ai un fichier de mise en page jade qui importe le corps des vues individuelles comme suit:

!!!
html

    head
        title= title || 'Title not set.'

    body
        #header
            h1 Header.

        #content!= body //- this renders the body of an individual view

        #footer
            p Footer.

Par exemple, la page d'index suivante:

p Welcome to the front page.

p This page serves as a now.js test.

Cela fonctionne bien. Cependant, je veux maintenant inclure deux bibliothèques javascript côté client spécifiquement pour cette page d'index (et donc pas très chaque page, c'est pourquoi je ne peux pas le mettre en tête de mise en page).

Cela marche:

//- import jquery
script(type='text/javascript', src='./jquery-1.5.2.min.js');

//- import now.js (hosts itself)
script(type='text/javascript', src='/nowjs/now.js')

//- import the chat client
script(type='text/javascript', src='./indexChatClient.js')

p Welcome to the front page.

p This page serves as a now.js test.

Cependant, cela charge les scripts dans le corps de la page complète, qui n'est pas du HTML valide, non?

Pour autant que je sache, les scripts doivent être chargés dans la tête si je veux le faire correctement, mais la section tête est gérée par le fichier de mise en page.

Alors, comment pourrais-je inclure correctement ces bibliothèques javascript côté client spécifiquement pour une certaine vue/page?

20
Tom

J'ai fait la même chose en utilisant la solution de ce fil:

http://groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac

Vous pouvez déclarer une variable "scripts" dans les options d'affichage:

app.js:

app.set('view options', { locals: { scripts: ['jquery.js'] } });  // You can declare the scripts that you will need to render in EVERY page

Que vous pouvez avoir un assistant qui rend les balises de script dans la tête de la mise en page

renderScriptTags () Code d'assistance:

app.helpers({ renderScriptTags: function(scripts) {
  return scripts.map(function(script) {
    return '<script src="scripts/' + script + '"></script>';
  }).join('\n ');

Dans le modèle de mise en page dans la section de tête, vous aurez:

- renderScriptTags(scripts)

Maintenant, pour ajouter un script sur la balise head, il vous suffit de pousser le script dans la variable "scripts" de votre modèle de contenu jade (modèle de corps):

- scripts.Push('myscript.js'); 

De cette façon, la page affichera jquery.js et myscript.js en tête de la page

[~ # ~] mise à jour [~ # ~]

Il semble que la dernière version express gère les locaux d'une manière différente, pour que cela fonctionne correctement, vous pouvez le faire (je ne suis pas sûr que ce soit la solution optimale, j'aurais besoin de creuser un peu)

Vous pouvez utiliser l'aide renderScriptTags () de la méthode précédente dans votre modèle de mise en page comme précédemment.

Mais ne définissez pas les variables de scripts en locales, créez plutôt une aide dynamique qui rendra une variable scripts disponible dans nos modèles:

app.dynamicHelpers({
  scripts: function(req, res){
    return ['jquery.js']; //this will be available in all views
  }
});

Et puis, pour ajouter un script spécifique, à partir de votre modèle de corps (exactement comme avant):

- scripts.Push('myscript.js'); 

Maintenant, pour cette vue spécifique, vous devriez avoir correctement rendu jquery.js et myscript.js

20
BFil

Vous pouvez les avoir sur la mise en page et spécifier les bibliothèques à charger sur les "contrôleurs".

// layout.jade
!!!
html

    head
        title= title || 'Title not set.'
        -each script in scripts 
          script(type='text/javascript', src= script)
    body
        #header
            h1 Header.

        #content!= body //- this renders the body of an individual view

        #footer
            p Footer.

Et votre "contrôleur":

// app.js
app.get('/', function (req, res) {
  res.render({
    scripts: ['jquery.min.js', '/nowjs/now.js']
  }
}
39
masylum

Il est possible de le faire The Right Way (tm) dans le dernier Jade (0.28.1) en le gardant à l'intérieur des modèles/vues, sans pirater le contenu des pages (liens de script) ailleurs:

  • Déclarez la tête en tant que bloc nommé dans votre modèle:
 doctype 5 
 html 
 tête 
 // bloc nommé nous permet d'ajouter des entrées de tête personnalisées dans chaque page 
 tête de bloc 
 lien title = title 
 (rel = 'stylesheet', href = '/ css/style.css') 
 script (type = "text/javascript", src = "/ js/some- default-script.js ") 
 corps 
 contenu du bloc 
  • Ajoutez vos éléments d'en-tête spécifiques à la page (y compris les balises de script) dans vos vues:
 étend la disposition 
 
 // ici nous référençons la tête du modèle et y ajoutons 
 bloc ajoutent la tête 
 meta (nom = "quelque chose", content = "blah") 
 lien (href = "/ css/another.css", rel = "feuille de style", type = "text/css") 
 style 
 div .foo {
 position: absolue; 
} 
 script (src = "/ js/page-specific-script.js") 
 
 bloquer le contenu 
 # page-contents-suit 
8
Gilead

Voici une autre façon de le faire (en utilisant la réponse de ShadowCloud). En généralisant un peu, vous pouvez spécifier des scripts locaux et distants, puis les reporter jusqu'à après le chargement de la page:

app.js:

app.dynamicHelpers({
    scripts: function() {
        //scripts to load on every page
        return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
    }
});

vous pouvez ensuite ajouter des scripts locaux ou distants à tout moment dans une vue

//- local script
- scripts.Push('js/myPage.js');
//- remote script ( note: this is a schemeless url. You can use http(s)? ones too )
- scripts.Push('//platform.Twitter.com/widgets.js')

layout.jade: (Je le mets à la fin du corps pour charger d'abord les trucs visibles, mais ça peut vraiment aller n'importe où)

//- Bring the scripts into a client-side array,
//-    and attach them to the DOM one by one on page load
script
    var page_scripts = !{'["' + scripts.join('","') + '"]'};
    function loadJS() {
        for(var i in page_scripts) {
            var e = document.createElement("script");
            e.src = page_scripts[i];
            document.body.appendChild(e);
        }
    }
    // Check for browser support of event handling capability
    if (window.addEventListener)
        window.addEventListener("load", loadJS, false);
    else if (window.attachEvent)
        window.attachEvent("onload", loadJS);
    else window.onload = loadJS;
2
jhoff

Je suppose que le problème (en lisant brièvement ceci) est que vous ne "videz" pas le tableau, en définissant sa longueur sur 0 pour supprimer les anciennes valeurs, donc chaque demande pourrait simplement pousser de plus en plus de chaînes

2
tjholowaychuk

Je ne sais pas à quoi servent les approches jusqu'à présent. Pour moi, il est beaucoup plus propre de faire ce qui suit ...

layout.jade:

doctype html
html
  head
    title= title
    block headscripts  // placeholder for scripts that need to be in the <head>
    link(rel='stylesheet', href='/styles/style.css')
    block styles       // placeholder for styles
  body
    block content
    script(src='/libs/jquery/dist/jquery.min.js') // this will render before all scripts in every page
    block scripts  // placeholder for scripts that go in the body

somepage.jade:

extends layout

block styles  // this will render in the <head>
  link(rel='stylesheet', href='/styles/films.css')
  link(rel='stylesheet', href='/styles/pagination.css')

block headscripts  // this will also render in the <head>
  script(src='/js/somescript.js')

block content
  h1= title
  div.someotherstuff

block scripts  // this will render at the end of the body
  script(src='/js/libs/someotherscript.js')
  scirpt(src='/libs/doT/doT.js')

De cette façon, peu importe où dans votre .jade les pages que vous placez vos blocs, elles seront toujours affichées aux bons endroits.

1
Stephen Collins