web-dev-qa-db-fra.com

Un fichier JS pour plusieurs pages

Je mets généralement tous les scripts JavaScript dans un seul fichier, par exemple. scripts.js (moins il y a de requêtes HTTP, mieux c'est). Donc, comme prévu, certains scripts sont nécessaires pour certaines pages, d'autres non.

Pour cibler une page spécifique, j'utilise quelque chose comme:

if ($("body#share").length > 0) {
    // Place the logic pertaining to the page with ID 'share' here...
}

// The file / script continues...

Autres ou meilleures suggestions? Merci!

Précision: J’étais pas à la recherche du pour et du contre entre la consolidation de plusieurs fichiers JS en un seul fichier volumineux et la conservation de plusieurs fichiers JS distincts. La réponse à cela est sûrement "dépend de la situation" (nous le savons). Ma question est la suivante: en supposant que toute ma logique JS soit placée dans un seul fichier volumineux, comment puis-je faire en sorte qu'un script particulier (un bloc de) s'exécute seulement lorsque la page correspondante est chargée? Une façon que je faisais auparavant est d'utiliser if ($('#id-of-target-element')) { /* run the script */}; y a-t-il un meilleur moyen?

44
moey

J'aime bien l'approche de Paul Irish ... vous ne devez pas la suivre exactement, mais l'idée générale est très solide.

Cela pourrait ressembler à quelque chose comme ça pour votre exemple

Html

<body id="share">

Votre javascript spécifique à la page

YourNamespace = {
  share : {
    init : function(){
      // Place the logic pertaining to the page with ID 'share' here...
    }
  }
}

Le Javascript de Paul Irish qui fait que la magie opère

UTIL = { 
  fire : function(func,funcname, args){
    var namespace = YourNamespace;  // indicate your obj literal namespace here

    funcname = (funcname === undefined) ? 'init' : funcname;
    if (func !== '' && namespace[func] && typeof namespace[func][funcname] == 'function'){
      namespace[func][funcname](args);
    }
  }, 

  loadEvents : function(){
    var bodyId = document.body.id;

    // hit up common first.
    UTIL.fire('common');

    // do all the classes too.
    $.each(document.body.className.split(/\s+/),function(i,classnm){
      UTIL.fire(classnm);
      UTIL.fire(classnm,bodyId);
    });

    UTIL.fire('common','finalize');
  }
};

// kick it all off here 
$(document).ready(UTIL.loadEvents);

Donc, la ligne que vous voyez directement ci-dessus lancera le suivant

YourNamespace.common.init()
YourNamespace.share.init()
YourNamespace.common.finalize()

Lisez son article sur le blog et quelques-unes des variations qui en découlent.

24
Charlino

Une autre option est que vous pourriez avoir, dans le code HTML

<script>
    callYourJSFunctionHere();  /*Things you would want to happen on Page load*/
</script>

Cela suivra le flux normal de la page. Par conséquent, si vous jouez avec des éléments de la page, vous devrez placer cette partie <script> au bas de la page, une fois que tous les éléments ont été chargés par le navigateur.

Je ne suis pas sûr à 100% que cela soit plus efficace que la solution actuelle, mais d'un autre côté, cela indiquera à quelqu'un qui regarde votre page HTML quel JavaScript sera exécuté lors du chargement de la page. Cela pourrait être utile en termes de maintenance sur la route .... pas tellement un jeu de devinettes quant à quel script est exécuté lorsque la page est chargée.

J'espère que cela t'aides!

5
blo0p3r

Votre suggestion semble OK. J'utiliserais cependant un HTML 5 data- attribut pour marquer chaque page de la manière suivante:

<body data-title="my_page_title">

Vous pouvez ensuite écrire du code javascript conditionnel en cochant cette propriété (à partir de jQuery 1.4.3):

if ($("body").data("title") === "my_page_title") {
    // Place the logic pertaining to the page with title 'my_page_title' here...
}

Cela vous permet de regrouper systématiquement tout le code d'une certaine page de manière judicieuse

5
Wesley

D'accord. Espérons que l'exemple de code le dira mieux que le mur de texte:


votre fichier one-and-only.js:

var MY_SITE = {
    // you have one namespace-object where you hold all your stuff
    main_page: {
        // inside you have smaller chunks, for specific pages or widgets
        // this one is for main page
        _init: function () {
        ... 
        },
        ... 
        showSplashScreen: function () {
        ...
        }      
    },
    ... 
    // but there are other pages
    contacts: { ... },
    // or widgets
    cool_menu: { ... },
    // and maybe you want to put common functions into dedicated block
    global_utilities: { ... },
    // and of course - the loader
    _start: function () {
        // here we simply call one _init of the page module that was specified 
        this[PAGE_TYPE]._init(); 
        // and more tricky stuff - we can search the page for elements
        // that contain special data-attribute, collect them
        var widgets = $('[data-our-widget]').each().getAttributeValue( 'data-or-widget' );
       // and then _init each of those widgets just like we did with main page 
        widgets.forEach( function (v) {
            this[v]._init();
        }
    }
};
document.on('ready', MY_SITE.start); // here we assume some random js framework

vos tags <script> sur la page:

<script>var PAGE_TYPE = 'main_page';</script>
<script src="one-and-only.js" />

vos éléments 'magiques' sur la page:

<div id="whatever" data-our-widget="cool_menu"> ... </div>

Avertissement: Ceci est une vue d'ensemble de haut niveau! Les détails de la mise en œuvre peuvent et doivent varier en fonction de vos besoins.

3
c69

Que diriez-vous de tester window.location? Cela semble le moyen évident pour moi.

Ou, comme vous semblez déjà le faire, vérifiez si les éléments requis sont présents. C'est une méthode assez robuste, je ne vois rien de mal à cela.

2
Anony-Mousse

Cela va être une vue d'ensemble de haut niveau, mais je recommande d'utiliser Backbone pour organiser la logique de chaque "vue" (ou page). J'utilise un élément racine et change la classe de cet élément pour basculer entre les autres vues (ou états) de la mise en page. Vous pouvez ensuite organiser les styles secondaires par classe et conserver un style principal sous l'ID.

HTML

<div id="layout" class="default">
    <!-- PUT DEFAULT HTML IN HERE -->
</div>
<script id="shareTemplate" type="text/html">
    <!-- PUT SHARE HTML IN HERE -->
</script>

CSS

#layout {
    /* primary style */
}

#layout.share {
   /* secondary style */
}

JavaScript

window.LayoutView = Backbone.View.extend({

    el: "#layout",

    shareTemplate: _.template($("#shareTemplate").html()),

    initialize: function() {
        this.render(shareTemplate, data);
        this.el.className = "share";
    },

    render: function(template, data) {
        $(this.el).html(template(data));
        return this;
    }

});

window.Layout = new LayoutView;
1
Ryan

Vous pouvez suivre votre approche, mais supposons que votre fichier javascript "cocktail" comporte 20k lignes de code et que vous l'incluiez dans tous vos fichiers html, même ceux qui affichent un "404" ou un "500". bande passante?

J'opte pour l'utilisation de différents js pour chaque page HTML et tout ce qui est utilisé sur plusieurs pages le dump dans un fichier "utils.js" ou ce que vous voulez appeler, par exemple

\www
  \pages
    \index.html
    \dashboard.html
    \account.html
    \ ...
  \scripts
    \index.js <- for index.html
    \dashboard.js <- for dashboard.html
    \account.js <- for account.html
    \ ...
    \utils.js|shared.js|sharedlib.js <- used by all pages

donc, fondamentalement, il en résultera:

  • 1 demande pour le HTML
  • 1 pour le script de page
  • 1 pour le script partagé, si utilisé
  • n pour css, mais je suppose est 1

Ceci est juste mes deux cents ..

0
ComputerSaysNo