Javascript templating without RJS, with JSON
One of the most convenient things about RJS is its ability to render a partial so you have all your view code in one place:
# task/index.html.erb
<ul id="task_list">
<%= render :partial => 'task', :collection => @tasks %>
</ul>
# task/_task.html.erb
<li>
<% if task.is_completed %>
<%= task.name %> - 开发者_StackOverflow中文版<%= task.completed_date %>
<% else %>
<%= task.name %> - UNCOMPLETED
<% end %>
...
</li>
Now I'm trying to move away from RJS and have the server respond in a small, nicely-formatted JSON instead of a huge chunk of JS + HTML.
Is there a way to keep my partial file and code as is without duplication and be able to add new items to the task list via JS without using RJS? I've looked into some of the javascript templating engines, but they all require me to maintain a separate ruby partial and a javacript template.
jQuery 1.4.3 will include the tmpl plugin (directly intergrated into jQuery) See http://api.jquery.com/jquery.tmpl/
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="http://nje.github.com/jquery-tmpl/jquery.tmpl.js"></script>
</head>
<body>
<ul id="movieList"></ul>
<script>
var movies = [
{ Name: "The Red Violin", ReleaseYear: "1998" },
{ Name: "Eyes Wide Shut", ReleaseYear: "1999" },
{ Name: "The Inheritance", ReleaseYear: "1976" }
];
var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";
/* Compile the markup as a named template */
$.template( "movieTemplate", markup );
/* Render the template with the movies data and insert
the rendered HTML under the "movieList" element */
$.tmpl( "movieTemplate", movies )
.appendTo( "#movieList" );
</script>
</body>
</html>
Mustache (http://mustache.github.com/) is a super simple template language with no logic what-so-ever. It has implementations in both Javascript and Ruby, and so templates can be rendered in either environment.
It is a bit trickier to use than RJS (or similar template languages). Since there is no logic in the templates, JSON objects must be extended with functions to provide more complex behavior.
Here is some example markup:
<div id="person_image"><img src="{{avatar_url}}"></img></div>
<div class="info">
<div id="person_location">{{location}}</div>
<h2 class="name">{{name}}</h2>
<div id="person_positions">
<ul class="positions">
{{#positions}}
<li>{{company_name}} — {{title}}</li>
{{/positions}}
</ul>
</div>
<div id="person_social_links">
<div class="social-profiles research-links">
{{#links}}
<a href="{{url}}" class="branded" target="_blank" style="background-image:url(https://www.google.com/s2/favicons?domain={{name}})"></a>
{{/links}}
</div>
</div>
</div>
Which will render this object:
{
"id":"4c0578d940cfd305ff00011c",
"name":"Steve Someguy",
"location":"Austin, Texas, United States",
"positions":[
{"title":"CEO", "company_name":"ACME, Inc.", "company_id":null},
{"title":"Director", "company_name":"Capsasin, Inc.", "company_id":"4c0578d940cfd305ff00011c"}
],
"links":[
{"name":"twitter.com","url":"http://twitter.com/spicyjs","image_url":"http://a3.twimg.com/profile_images/439463427/Picture_7_bigger.png"},
{"name":"twitter.com","url":"http://twitter.com/shadr","image_url":"http://a1.twimg.com/profile_images/20072132/me.jpg"},
{"name":"facebook.com","url":"http://facebook.com/shad.reynolds","image_url":"http://www.facebook.com/profile/pic.php?uid=AAAAAQAQm2JvEZLOpW8bCG-rToD8VQAAAAlFjZG9cIKwaX2wuA_Nspjn"}
]
}
Handlebars.js is a related project which is also gaining some traction, though the Ruby implementation does not appear to be as complete (http://yehudakatz.com/2010/09/09/announcing-handlebars-js/).
What you search for might be JsonML or Pure, I did find those long time ago at the bottom of the JSON.org page, but I have not come around to test them myself.
If you use them, please tell me how it goes.
I wish you good luck!
For a library-independant solution, you may want to look at Jon Resig's (creator of jQuery) micro-templating function on his blog:
http://ejohn.org/blog/javascript-micro-templating/
Not the best implementation but worth the read.
精彩评论