简体   繁体   中英

Rendering in backbone.js with underscore templates

I try to render a list of item using underscore's template. But it displays nothing.

I tried to create 2 views, one is a task and one is a task list, but I'm stuck at using template.

  • What does .render() do?
  • if I use template, do I still need to render?

I thought the data will map the template variable when you do this.$el.html(template_var) ?

 <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="http://underscorejs.org/underscore-min.js"></script> <script src="http://backbonejs.org/backbone-min.js"></script> <script type="text/template" id="task_list"> <li><%=title%></li> <li><%=priority%></li> </script> </script> <script type="text/javascript"> (function(){ window.App = { Models:{}, Collections:{}, Views:{} }; window.template = function(id){ return _.template( $('#' + id).html() ); } App.Models.Task = Backbone.Model.extend({ title: 'default', priority: 1 }); App.Collections.Task = Backbone.Collection.extend({ model: App.Models.Task }); App.Views.Task = Backbone.View.extend({ template: template('task_list'), render(){ var template = this.template( this.model.toJSON() ); console.log(template) this.$el.html(template); return this; } }) App.Views.Tasks = Backbone.View.extend({ tagName: 'ul', render: function(){ this.collection.each( this.addOne, this); return this; }, addOne: function(task){ var taskView = new App.Views.Task({ model: task}) taskView.render(); this.$el.append(taskView.render().el); } }) var tasks = new App.Collections.Task([ { title: 'Go to store', priority: 4 }, { title: 'Eat', priority: 3 }, { title: 'Sleep', priority: 4 } ]) var tasksView = new App.Views.Tasks({collection: tasks}) $('body').html(tasksView.el) })() </script> </body> </html> 

You were really close, but there were small problems.

Backbone does a lot of things, but one thing it doesn't do for you is the rendering logic, which is left completely up to the developer. So, you need:

  • a template to separate the HTML from the the JS logic.
  • a render function which does the rendering using your favorite technique, jQuery in our case.

A Backbone view always has a root DOM element ( el ) even if it was not rendered yet, which is a div by default if tagName isn't specified.

So your task view looked something like this when rendered:

<div>
    <li>Go to store</li>
    <li>4</li>
</div>

I changed the template a little to work.


I moved the CSS back to the HEAD section. This is a standard, but was not really one of the problem.


Default attributes in a model should be specified in the defaults property .


Defining function with the shorthand syntax like the following is only available in ES6 (ECMAScript 2015).

render(){

Starting with ECMAScript 2015 (ES6), a shorter syntax for method definitions on objects initializers is introduced. It is a shorthand for a function assigned to the method's name.

And to make it compatible with most browser , you should use:

render: function() {

You also forgot to call render on the list view.

$('body').html(tasksView.el)

Should be:

$('body').html(tasksView.render().el);

Since your code is inside an IIFE , you don't need to make your app and functions global with the window , a local var is enough and is a better coding practice.


 <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>Title</title> <!-- CSS should be in the head --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script> <script src="http://underscorejs.org/underscore.js"></script> <script src="http://backbonejs.org/backbone.js"></script> <script type="text/template" id="task_list"> <%=title%> (<%=priority%>) </script> <script type="text/javascript"> (function() { var App = { Models: {}, Collections: {}, Views: {} }; function template(id) { return _.template($('#' + id).html()); } App.Models.Task = Backbone.Model.extend({ defaults: { title: 'default', priority: 1 } }); App.Collections.Task = Backbone.Collection.extend({ model: App.Models.Task }); App.Views.Task = Backbone.View.extend({ template: template('task_list'), tagName: 'li', render: function() { var template = this.template(this.model.toJSON()); console.log(template) this.$el.html(template); return this; } }); App.Views.Tasks = Backbone.View.extend({ tagName: 'ul', render: function() { this.collection.each(this.addOne, this); return this; }, addOne: function(task) { var taskView = new App.Views.Task({ model: task }) this.$el.append(taskView.render().el); } }); var tasks = new App.Collections.Task([{ title: 'Go to store', priority: 4 }, { title: 'Eat', priority: 3 }, { title: 'Sleep', priority: 4 }]); var tasksView = new App.Views.Tasks({ collection: tasks }); $('body').html(tasksView.render().el); })() </script> </body> </html> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM