问题
Iam learning Backbone js and so I have started creating sample application.
BTW, iam facing one problem now ie., model is saving more than once in my database. I mean when you click 'Create User' , you'll see a form, so when I click that 'Create User' button, details are getting saved more than once in my DB and so all duplicate users info displayed in the home page.
Actually iam trying to practice this video: https://www.youtube.com/watch?v=FZSjvWtUxYk
The output would look like this: http://backbonetutorials.com/videos/beginner/#/new
Here is my Code:
<html>
<head>
<link rel="stylesheet"
href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.1/css/bootstrap.min.css">
<script type="text/javascript">
/*$.getJSON('api/users/1',function(data){
console.log(data);
});*/
</script>
</head>
<body>
<div class="container">
<h1> User Manager</h1>
<hr/>
<div class="page"></div>
</div>
<script type="text/template" id="user-list-template">
<a href="#/new" class="btn btn-primary">New User</a>
<hr/>
<table class="table stripped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<% _.each(users, function(user){ %>
<tr>
<td><%= user.get('firstName') %></td>
<td><%= user.get('lastName') %></td>
<td><%= user.get('age') %></td>
</tr>
<% }); %>
</tbody>
</table>
</script>
<script type="text/template" id="add-user-template">
<legend>Create User</legend>
<form class="add-user-form">
First Name <input type="text" id="firstName"/><br/>
Last Name <input type="text" id="lastName"/><br/>
Age <input type="text" id="age"/><hr/>
<input type="submit" value="Create User">
</form>
</script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script type="text/javascript">
var UsersList = Backbone.Collection.extend({
url: 'api/users'
});
var User = Backbone.Model.extend({
urlRoot: 'api/users'
});
var UsersListView = Backbone.View.extend({
el: '.page',
render: function(){
var that = this;
var users = new UsersList();
users.fetch({
success: function(usersList){
var template = _.template($('#user-list-template').html())({users: usersList.models});
that.$el.html(template);
}
});
}
});
var AddUserView = Backbone.View.extend({
el: '.page',
render: function(){
var template = _.template($('#add-user-template').html())({user:null});
this.$el.html(template);
},
events: {
'submit .add-user-form': 'saveOrUpdateUser'
},
saveOrUpdateUser: function(e){
e.preventDefault();
var userDetails = {firstName: $('#firstName').val(), lastName: $('#lastName').val(), age: $('#age').val()};
var user = new User();
user.save(userDetails,{ //SEEMS LIKE HERE HAVING SOME PROBLEM
success: function(){
console.log('INSIDE SUCCESS..');
router.navigate('',{trigger: 'true'});
}
});
}
});
var Router = Backbone.Router.extend({
routes:{
'':'home',
'new':'addUser'
}
});
var router = new Router();
router.on('route:home',function(){
var usersListView = new UsersListView();
usersListView.render();
});
router.on('route:addUser',function(){
var addUserView = new AddUserView();
addUserView.render();
});
Backbone.history.start();
</script>
</body>
</html>
Please suggest me what went wrong and how to fix this?
回答1:
@MarciaYudkin you'll notice that when you first load your site and create a user, that first user does not save a duplicate. However, the next time you fill out a CreateUser
form, the user will get saved twice. What's happening here is that you are suffering from Zombie Views! (Ahh!)
A Zombie View is a view that you thought went away, but in fact remains in the background. Since they're still alive, they are also still bound its view events
. The zombie view you detected in your code is:
router.on('route:addUser',function(){
var addUserView = new AddUserView(); // <---Right here!
addUserView.render();
});
Every time a user follows the route:addUser
route they end up creating a new AddUserView
. This view renders itself and attaches itself to the DOM. You would think that since you "removed" your old view from the DOM, it would simply disappear, right? Well, it does---from the DOM---but not from memory! Since that view still has event bound to the DOM, it does not get garbage collection. When a DOM element that was bound to any previous views is triggered (like by clicking it), the current, as well as all the old, undisposed, views are still bound to it, and all of them respond to the trigger. That's what's happening to you. Here, see this fiddle I cooked up.
How to fix it
The way out of this is to keep a reference to the view around, so that you could properly dispose of it. So, for example, you could attach a reference to the view in your router, and do,
router.on('route:addUser',function(){
// If the view exists, remove it
if (router.addUserView) {
router.addUserView.remove();
router.addUserView.off();
}
router.addUserView = new AddUserView();
router.addUserView.render();
});
Here we call Backbone.View.remove(), which really does this.$el.remove()
behind the scences, effectively removing the DOM elements referred to by our view and releasing the bound events. Now our view can be garbage collected!
You can see how I answered this question recently for another angle on this: Saving User Data more than once. And I think I'd be remiss if I didn't include Derick Bailey's seminal article on zombie views (from where I got most of my information), Zombies! RUN! (Managing Page Transitions In Backbone Apps)
来源:https://stackoverflow.com/questions/28054773/backbone-js-model-save-more-than-once