[英]How can I integrate handlebars with backbone
我有一個簡單的單頁應用程序,供我自己學習。 該頁面具有我提供的所有服務的 UL。 此列表來自 JSON。 每項服務旁邊都有一個價格,以及一個復選框,如果用戶需要該服務,可以選擇該復選框。
在列表下有所有選定服務的總價。 基於此,你能告訴我我做錯了什么嗎? 我正在嘗試將服務列表集成為把手模板。 這是 HTML
<head>
<meta charset="utf-8" />
<title>Your first Backbone.js App | Tutorialzine </title>
<!-- Google web fonts -->
<link href="http://fonts.googleapis.com/css?family=PT+Sans:400,700" rel='stylesheet' />
<!-- The main CSS file -->
<link href="http://localhost/backbone-demo/assets/css/style.css" rel="stylesheet" />
</head>
<body>
<form id="main" method="post" action="submit.php">
<h1>My Services</h1>
<div id="serviceTable"></div>
<ul id="services">
<script id="services-template" type="text/x-handlebars-template">
<!-- The services will be inserted here via handlebars-->
{{#each services}}
<li>
<input type="checkbox" value="1" name="{{title}}"/> {{title}}
<span>${{price}} </span>
</li>
{{/each}}
</script>
</ul>
<p id="total">total: <span>$0</span></p>
<input type="submit" id="order" value="Order" />
</form>
<!-- JavaScript Includes -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://localhost/backbone-demo/assets/js/libs/underscore.min.js"></script>
<script src="http://localhost/backbone-demo/assets/js/libs/backbone.min.js"></script>
<script src="http://localhost/backbone-demo/assets/js/libs/handlebars.js"></script>
<script src="http://localhost/backbone-demo/assets/js/script.js"></script>
</body>
這是Javascript:
$(function(){
// Create a model for the services
var Service = Backbone.Model.extend({
// Will contain three attributes.
// These are their default values
defaults:{
title: 'My service',
price: 100,
checked: false
},
// Helper function for checking/unchecking a service
toggle: function(){
this.set('checked', !this.get('checked'));
}
});
// Create a collection of services
var ServiceList = Backbone.Collection.extend({
// Will hold objects of the Service model
model: Service,
// Return an array only with the checked services
getChecked: function(){
return this.where({checked:true});
}
});
//Retrieve the list of services
$.ajax({
type: "GET",
url: "assets/services.json",
async: true,
success: function(response){
// Prefill the collection with a number of services.
var services = new ServiceList(response);
var ServiceView = Backbone.View.extend({
tagName: 'li',
events:{
'click': 'toggleService'
},
initialize: function(){
// Set up event listeners. The change backbone event
// is raised when a property changes (like the checked field)
this.listenTo(services, 'change', this.render);
},
render: function(){
var tpl = Handlebars.compile($("#services-template").html());
//console.log(this.$el.selector);
this.$el.html(tpl({services: services.toJSON()}));
//console.log(this.$el);
$('#serviceTable').append(this.$el);
//document.getElementById('serviceTable').innerHTML = serviceData;
// Create the HTML
/* this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
this.$('input').prop('checked', this.model.get('checked')); */
// Returning the object is a good practice
// that makes chaining possible
return this;
},
toggleService: function(){
this.model.toggle();
}
});
// The main view of the application
var App = Backbone.View.extend({
// Base the view on an existing element
el: $('#main'),
initialize: function(){
// Cache these selectors
this.total = $('#total span');
this.list = $('#services');
// Listen for the change event on the collection.
// This is equivalent to listening on every one of the
// service objects in the collection.
this.listenTo(services, 'change', this.render);
// Create views for every one of the services in the
// collection and add them to the page
services.each(function(service){
var view = new ServiceView({ model: service });
this.list.append(view.render().el);
}, this); // "this" is the context in the callback
},
render: function(){
// Calculate the total order amount by agregating
// the prices of only the checked elements
var total = 0;
console.log(services.getChecked());
Handlebars.each(services.getChecked(), function(elem){
console.log(total);
total += elem.get('price');
});
// Update the total price
this.total.text('$'+total);
return this;
}
});
new App();
}
});
});
以下是您的代碼的可行片段。 您已經定義了一個ServiceView
,它是為您的集合中的每個服務創建的,但是在此視圖中,您正在處理整個集合,而不是this.model
並且您的把手模板中有一個 for 循環。
這意味着您最終顯示的集合與集合中的模型一樣多。 下面的示例將列表復制兩次,因為列表中有 2 條記錄。
有兩種可能的解決方案:
將您的ServiceView
重命名為ServicesView
並刪除 App 初始化中的循環。
刪除模板中的循環並將調用更改為this.$el.html(tpl(this.model.toJSON()));
// Create a model for the services var Service = Backbone.Model.extend({ // Will contain three attributes. // These are their default values defaults:{ title: 'My service', price: 100, checked: false }, // Helper function for checking/unchecking a service toggle: function(){ this.set('checked', !this.get('checked')); } }); // Create a collection of services var ServiceList = Backbone.Collection.extend({ // Will hold objects of the Service model model: Service, // Return an array only with the checked services getChecked: function(){ return this.where({checked:true}); } }); //Retrieve the list of services $.ajax({ type: "GET", url: "http://www.mocky.io/v2/588b429d300000d11afa8d97", async: true, success: function(response){ // Prefill the collection with a number of services. var services = new ServiceList(response); var ServiceView = Backbone.View.extend({ tagName: 'li', events:{ 'click': 'toggleService' }, initialize: function(){ // Set up event listeners. The change backbone event // is raised when a property changes (like the checked field) this.listenTo(services, 'change', this.render); }, render: function(){ var tpl = Handlebars.compile($("#services-template").html()); //console.log(this.$el.selector); this.$el.html(tpl({services: services.toJSON()})); //console.log(this.$el); $('#serviceTable').append(this.$el); //document.getElementById('serviceTable').innerHTML = serviceData; // Create the HTML /* this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>'); this.$('input').prop('checked', this.model.get('checked')); */ // Returning the object is a good practice // that makes chaining possible return this; }, toggleService: function(){ this.model.toggle(); } }); // The main view of the application var App = Backbone.View.extend({ // Base the view on an existing element el: $('#main'), initialize: function(){ // Cache these selectors this.total = $('#total span'); this.list = $('#services'); // Listen for the change event on the collection. // This is equivalent to listening on every one of the // service objects in the collection. this.listenTo(services, 'change', this.render); // Create views for every one of the services in the // collection and add them to the page services.each(function(service){ var view = new ServiceView({ model: service }); this.list.append(view.render().el); }, this); // "this" is the context in the callback }, render: function(){ // Calculate the total order amount by agregating // the prices of only the checked elements var total = 0; console.log(services.getChecked()); Handlebars.each(services.getChecked(), function(elem){ console.log(total); total += elem.get('price'); }); // Update the total price this.total.text('$'+total); return this; } }); new App(); } });
<form id="main" method="post" action="submit.php"> <h1>My Services</h1> <div id="serviceTable"></div> <ul id="services"> <script id="services-template" type="text/x-handlebars-template"> <!-- The services will be inserted here via handlebars--> {{#each services}} <li> <input type="checkbox" value="1" name="{{title}}"/> {{title}} <span>${{price}} </span> </li> {{/each}} </script> </ul> <p id="total">total: <span>$0</span></p> <input type="submit" id="order" value="Order" /> </form> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js"></script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.