Alors que #2 pourrait être "plus facile" pour vous en tant que développeur, il ne fournit moteur de recherche, de l'analyse. Et oui, si Google trouve votre fournir un contenu différent, vous pourriez être pénalisé (je ne suis pas un expert, mais j'ai entendu dire que cela ce produit).
Les deux RÉFÉRENCEMENTS et de l'accessibilité (et pas seulement pour la personne handicapée, mais l'accessibilité via des appareils mobiles, des appareils à écran tactile, et d'autres non-standard de l'informatique / l'internet a permis à ces plates-formes), les deux ont une semblable philosophie sous-jacente: sémantiquement riche de balisage qui est "accessible" (c'est à dire qui peuvent être consultées, lire, traitée ou utilisée d'une autre manière) via ces différents navigateurs. Un lecteur d'écran, un moteur de recherche, de robot ou d'un utilisateur avec JavaScript activé, il devrait être en mesure d'utiliser/index/comprendre de votre site sur les fonctionnalités de base sans problème.
pushState
n'est pas à ajouter à ce fardeau, selon mon expérience. Il apporte seulement une réflexion après coup, et "si nous avons le temps" qui est à l'avant-garde du développement web.
Ce que vous décrivez dans l'option #1 est généralement la meilleure façon de faire - mais, comme d'autres l'accessibilité et le référencement SEO de questions, le faire avec pushState
dans un JavaScript-lourds application requiert une planification à l'avance ou il deviendra un fardeau important. Il doit être cuit à la page et de l'architecture de l'application de la start - mise en conformité est douloureux et causer plus de duplication que ce qui est nécessaire.
J'ai travaillé avec pushState
SEO, et récemment pour un couple de différentes applications, et j'ai trouvé ce que je pense est une bonne approche. Il suit globalement votre point #1, mais ne représente pas la duplication de code html / modèles.
Plus d'informations peuvent être trouvées dans ces deux billets de blog:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
et
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
L'essentiel, c'est que j'utilise ERB ou HAML modèles (l'exécution de Ruby on Rails, Sinatra, etc) de mon côté serveur de rendu et de créer le côté client de modèles que l'épine Dorsale pouvez utiliser, ainsi que pour mon Jasmin JavaScript specs. Cela permet de réduire la duplication de balisage entre le côté serveur et côté client.
À partir de là, vous avez besoin de prendre quelques mesures supplémentaires afin d'avoir l'option JavaScript de votre travail avec le HTML qui est affiché par le serveur véritable amélioration progressive; en prenant le balisage sémantique qui les a livrés et de le renforcer avec du JavaScript.
Par exemple, je suis en train de construire une image de la galerie de l'application avec pushState
. Si vous demandez /images/1
à partir du serveur, il va rendre l'ensemble de la galerie d'image sur le serveur et d'envoyer le tout le code HTML, CSS et JavaScript en bas de votre navigateur. Si vous avez désactivé JavaScript, il fonctionne parfaitement bien. Chaque action que vous prenez va demander une URL différente à partir du serveur, et le serveur à rendre l'ensemble de la marge pour votre navigateur. Si vous avez activé JavaScript, cependant, le JavaScript va chercher le déjà rendu HTML avec un peu de variables générées par le serveur à partir de là.
Voici un exemple:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Une fois que le serveur rend cela, le JavaScript, le ramasser (à l'aide d'un Backbone.js vue dans cet exemple)
FooView = Backbone.View.extend({
events: {
"change #name": "setName",
"click #say": "sayName"
},
setName: function(e){
var name = $(e.currentTarget).val();
this.model.set({name: name});
},
sayName: function(e){
e.preventDefault();
var name = this.model.get("name");
alert("Hello " + name);
},
render: function(){
// do some rendering here, for when this is just running JavaScript
}
});
$(function(){
var model = new MyModel();
var view = new FooView({
model: model,
el: $("#foo")
});
});
C'est un exemple très simple, mais je pense qu'il obtient le point à travers.
Quand je instante la vue après le chargement de la page, je suis fournissant le contenu existant de la forme qui a été rendu par le serveur, à l'instance de vue que l' el
pour la vue. Je suis pas d'appel de rendu ou d'avoir le point de vue de générer un el
pour moi, lorsque le premier point de vue est chargé. J'ai une méthode de rendu disponibles pour une fois que la vue est en place et en cours d'exécution et que la page est tout au JavaScript. Cela me permet de re-rendre la vue plus tard si j'en ai besoin.
En cliquant sur le "Say My Name" bouton avec JavaScript activé va provoquer une boîte d'alerte. Sans JavaScript, il serait de publier sur le serveur et que le serveur pourrait rendre le nom d'un élément html, quelque part.
Modifier
Considérons un exemple plus complexe, où vous avez une liste qui doit être relié (d'après les commentaires ci-dessous)
Disons que vous avez une liste d'utilisateurs dans un <ul>
balise. Cette liste a été rendue par le serveur lorsque le navigateur fait une demande, et le résultat ressemble à quelque chose comme:
<ul id="user-list">
<li data-id="1">Bob
<li data-id="2">Mary
<li data-id="3">Frank
<li data-id="4">Jane
</ul>
Maintenant, vous avez besoin d'une boucle sur cette liste et joindre une épine Dorsale modèle et de la vue à chacune de l' <li>
articles. Avec l'utilisation de l' data-id
d'attribut, vous pouvez trouver le modèle que chaque balise vient facilement. Vous aurez alors besoin d'une collecte de vue et le point de vue qui est assez intelligent pour s'attacher à ce html.
UserListView = Backbone.View.extend({
attach: function(){
this.el = $("#user-list");
this.$("li").each(function(index){
var userEl = $(this);
var id = userEl.attr("data-id");
var user = this.collection.get(id);
new UserView({
model: user,
el: userEl
});
});
}
});
UserView = Backbone.View.extend({
initialize: function(){
this.model.bind("change:name", this.updateName, this);
},
updateName: function(model, val){
this.el.text(val);
}
});
var userData = {...};
var userList = new UserCollection(userData);
var userListView = new UserListView({collection: userList});
userListView.attach();
Dans cet exemple, l' UserListView
, passe en boucle sur tous les de la <li>
balises et attacher un objet de vue avec le bon modèle pour chacun. il met en place un gestionnaire d'événement pour le modèle de changement de nom de l'événement et met à jour l'affichage du texte de l'élément lorsqu'un changement se produit.
Ce type de processus, de prendre le code html que le serveur de rendu et d'avoir mon JavaScript prendre le dessus et de le lancer, il est un excellent moyen de bouger les choses pour le RÉFÉRENCEMENT, l'Accessibilité et l' pushState
de soutien.
Espérons que cela aide.