2010-05-06 15 views
5

Con un'applicazione a singola pagina, in cui cambio l'hash e carico e cambio solo il contenuto della pagina, sto cercando di decidere come gestire il codice JavaScript che ognuno " pagina "potrebbe essere necessario.Best practice per la gestione di JavaScript su un'applicazione a singola pagina

Ho già un modulo Cronologia che monitora l'hash della posizione che potrebbe apparire come domain.com/#/company/about e una classe Page che utilizzerà XHR per ottenere il contenuto e inserirlo nell'area del contenuto.

function onHashChange(hash) { 
    var skipCache = false; 
    if(hash in noCacheList) { 
     skipCache = true; 
    } 
    new Page(hash, skipCache).insert(); 
} 


// Page.js 
var _pageCache = {}; 
function Page(url, skipCache) { 

    if(!skipCache && (url in _pageCache)) { 
     return _pageCache[url]; 
    } 
    this.url = url; 
    this.load(); 

} 

La cache deve consentire alle pagine che sono già state caricate di saltare l'XHR. Sto anche memorizzando il contenuto in un documentoFragment e poi estraendo il contenuto corrente dal documento quando inserisco il nuovo Page, quindi il browser dovrà solo creare il DOM per il frammento una volta.

Saltare la cache potrebbe essere desiderato se la pagina contiene dati sensibili al tempo.

Ecco cosa ho bisogno di aiuto per decidere su: È molto probabile che qualsiasi pagina caricata abbia il proprio codice JavaScript per controllare la pagina. Come se la pagina usasse le Tab, avesse bisogno di una presentazione, avesse una sorta di animazione, avesse un modulo Ajax o che cosa tu abbia.

Qual è esattamente il modo migliore per andare in giro a caricare quel JavaScript nella pagina? Includere i tag di script nel documentoFragment che torno dall'XHR? Cosa succede se ho bisogno di saltare la cache e di scaricare nuovamente il frammento. Sento che lo stesso identico JavaScript chiamato una seconda volta potrebbe causare conflitti, come la redeclaring delle stesse variabili.

Sarebbe il modo migliore di collegare gli script alla testa quando si afferra il nuovo Page? Ciò richiederebbe alla pagina originale di conoscere tutte le risorse di cui ogni altra pagina potrebbe aver bisogno.

E oltre a conoscere il modo migliore per includere tutto, non dovrò preoccuparmi della gestione della memoria e delle possibili perdite di caricamento di così tanti diversi bit JavaScript in una singola istanza di pagina?

+0

Che cos'è un'app a pagina singola? –

+1

Dove si carica la prima pagina dal server e tutto il resto utilizza XHR, anziché le richieste di una pagina intera. Facebook è un esempio. – seanmonstar

+0

jQuery è tuo amico. Compralo da bere –

risposta

0

Non ho mai costruito un sito di questo tipo, quindi non so se sia la pratica più buona, ma inserirò nella risposta alcune informazioni di controllo (come un commento o un'intestazione HTTP), e lascerò lo script del caricatore gestire il cheching di ridondanza/dipendenza e aggiungere i tag dello script all'intestazione.

0

Hai il controllo su quelle pagine caricate? In caso contrario, consiglierei di inserire la pagina caricata in un IFrame.

Prendere gli script di pagina fuori dal loro contesto e inserirli in testa o aggiungerli a un altro elemento HTML può causare problemi se non si sa esattamente come viene costruita la pagina.

Se si ha il pieno controllo delle pagine caricate, si consiglia di convertire tutto il codice HTML in JS. Può sembrare strano ma, in realtà, un convertitore HTML-> JS non è così lontano. È possibile iniziare con Pure JavaScript HTML Parser e lasciare che il parser restituisca il codice JS, che crea il DOM utilizzando JQuery, ad esempio.

In realtà stavo per percorrere quella strada per un po 'di tempo su una webapp su cui ho iniziato a lavorare, ma ora l'ho consegnato a un appaltatore che ha convertito tutte le mie pagine JS pure in HTML + JQuery, qualunque cosa faccia il suo lavoro quotidiano produttivo, non me ne importa, ma ero davvero preso da quel semplice approccio web-app JS e sicuramente lo proverei.

+0

Ho il controllo delle pagine. Stavo considerando un parser JS. Ma sto già creando le pagine in PHP, e dal momento che PHP è molto più veloce di JS, stavo solo per restituire l'HTML. – seanmonstar

1

Se capisco correttamente il caso, stai provando a prendere un sito che al momento ha pagine già fatte per la normale navigazione, e vuoi estrarle tramite ajax, per salvare te stesso la pagina-ricarica?

Quindi, quando ciò accade, non è necessario ricaricare i tag di script per tali pagine, a meno che non siano già caricati nella pagina?

Se questo è il caso, si potrebbe provare a prendere tutti i tag dalla pagina prima di inserire il nuovo HTML nel DOM:

//first set up a cache of urls you already have loaded. 
var loadedScripts = []; 

//after user has triggered the ajax call, and you've received the text-response 
function clearLoadedScripts(response){ 
    var womb = document.createElement('div'); 
    womb.innerHTML = response; 
    var scripts = womb.getElementsByTagName('script'); 
    var script, i = scripts.length; 
    while (i--) { 
     script = scripts[i]; 
     if (loadedScripts.indexOf(script.src) !== -1) { 
      script.parentNode.removeChild(script); 
     } 
     else { 
      loadedScripts.push(script.src); 
     } 
    } 

    //then do whatever you want with the contents.. something like: 
    document.body.innerHTML = womb.getElementsByTagName('body')[0].innerHTML); 

} 
+0

Questa è un'implementazione davvero fantastica ... – gnarf

0

Per me suona come si sta creando una pagina singola app dall'inizio (cioè non ri-factoring di un sito esistente).

diverse opzioni che posso pensare:

  1. lasciare che il controllo del server quali tag di script sono compresi. passare un elenco di tag di script già caricati con la richiesta XHR e fare in modo che il server decida quali script aggiuntivi devono essere caricati.
  2. Carica tutte script prima mano (forse aggiungerli al DOM dopo caricata la pagina per risparmiare tempo) e poi non pensarci più. Per gli script che devono inizializzare l'interfaccia utente, è sufficiente che ciascuna chiamata alla pagina richiesta includa un tag script che chiama una funzione di inizializzazione globale con il nome della pagina.
  3. Ogni pagina richiesta chiama una funzione JS che si occupa degli script di caricamento/memorizzazione nella cache. Questa funzione sarebbe accessibile dall'ambito globale e avrebbe il seguente aspetto: require_scripts('page_1_init', 'form_code', 'login_code') Quindi basta che la funzione mantenga un elenco di script caricati e aggiunga solo i tag script DOM per gli script che non sono ancora stati caricati.
0

Si potrebbe usare un caricatore script come YUI Loader, LAB.js o altro come jaf

Jaf fornisce meccanismo per caricare viste (frammenti di codice HTML) e le loro rispettive js, file CSS per creare singola pagina app. Controlla l'app di esempio per la lista di cose da fare. Sebbene non sia completo, ci sono ancora molte librerie utili che puoi usare.

1

Oh ragazzo sei fortunato. Ho appena fatto tutta questa ricerca per il mio progetto.

1: L'evento hash/manager si dovrebbe utilizzare è BBQ di Ben Alman: http://benalman.com/projects/jquery-bbq-plugin/

2: Per rendere i motori di ricerca ti amo, è necessario seguire questo molto chiara serie di regole: http://code.google.com/web/ajaxcrawling/docs/specification.html

Ho trovato questo ritardo e il gioco e ho dovuto cancellare un sacco del mio codice. Sembra che dovrai scartarne anche un po ', ma ne otterrai molto di più.

Buona fortuna!

+0

grazie per questo articolo su google.com ajaxcrawling. Lo stavo cercando. – seanmonstar

+0

NP! Si prega di contrassegnare questo come la risposta se è quello che stavi cercando. – Matrym

+0

stavo cercando il collegamento da solo, ma non penso che questo risponda alla domanda, mi dispiace. Sono più interessato alla gestione di Javascript richiesto da varie pagine, alla gestione delle variabili appena dichiarate, agli eventi allegati e di separazione e alla gestione della memoria. – seanmonstar

0

Personalmente, vorrei trasmettere JSON invece di HTML grezzo:

{ 
    "title": "About", 
    "requires": ["navigation", "maps"], 
    "content": "<div id=…" 
} 

Questo consente di inviare i metadati, come una serie di script necessari, insieme al contenuto.Dovresti quindi usare un caricatore di script, come uno di quelli menzionati sopra, o il tuo, per controllare quali sono già caricati e tirare giù quelli che non lo sono (inserendoli nello <head>) prima di eseguire il rendering della pagina.

Invece di includere script in linea per la logica specifica della pagina, utilizzerei classi, ID e attributi predeterminati su elementi che richiedono una gestione speciale. Puoi attivare un evento "onrender" o lasciare che ogni elemento logico registri un callback di rendering che il tuo caricatore di pagine chiamerà dopo che una pagina è stata sottoposta a rendering o caricata per la prima volta.

Problemi correlati