【问题标题】:Backbone js Model Save more than once骨干js模型保存不止一次
【发布时间】:2015-03-19 05:42:30
【问题描述】:

我正在学习 Backbone js,所以我已经开始创建示例应用程序。

顺便说一句,我现在面临一个问题,即模型在我的数据库中保存了不止一次。我的意思是当你点击 'Create User' 时,你会看到一个表单,所以当我点击 'Create User' 按钮时,详细信息会在我的数据库中多次保存,因此所有重复的用户主页上显示的信息。

其实我正在尝试练习这个视频:https://www.youtube.com/watch?v=FZSjvWtUxYk

输出如下所示:http://backbonetutorials.com/videos/beginner/#/new

这是我的代码:

<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>

请建议我出了什么问题以及如何解决这个问题?

【问题讨论】:

  • 我认为问题在于您没有提供idAttribute,因此当您尝试更新用户时,它没有更新的参考点。所以它会创建另一个
  • @Scriptable 我猜默认情况下它将具有 'id' 属性,据我所知,只有当我们的 id 名称与 'id' 不同时,我们才需要使用 idAttribute ,例如: 'idAttribute : userId'
  • 模型中有id字段吗?
  • @Scriptable Iam 认为 'id' 应该是默认值,如果我们不指定它,则在模型中。你真的认为“id”会导致问题吗?
  • Backbone 默认使用 REST http 请求,所以使用 ID 来更新/获取/删除。如果没有指定 id 它不能做这些事情。在控制台窗口中检查您的 ajax 请求,检查您发回服务器的内容。在服务器上检查您收到的内容。如果您无法识别记录,则无法更新它。它会插入

标签: javascript jquery backbone.js


【解决方案1】:

@MarciaYudkin 您会注意到,当您第一次加载站点并创建用户时,第一个用户不会保存副本。但是,下次您填写 CreateUser 表单时,用户将被保存两次。这里发生的情况是您正遭受僵尸视图! (啊!)

僵尸视图是您认为已消失但实际上仍保留在背景中的视图。由于他们还活着,他们也仍然被其视图events绑定。您在代码中检测到的僵尸视图是:

router.on('route:addUser',function(){
    var addUserView = new AddUserView(); // <---Right here!
    addUserView.render();
});

每次用户遵循route:addUser 路由时,他们最终都会创建一个新的AddUserView。此视图呈现自身并将自身附加到 DOM。你会认为既然你从 DOM 中“移除”了你的旧视图,它就会消失,对吧?嗯,它确实——来自 DOM——但不是来自内存!由于该视图仍然有绑定到 DOM 的事件,因此它不会进行垃圾回收。当绑定到任何先前视图的 DOM 元素被触发(例如通过单击它)时,当前以及所有旧的、未处理的视图仍然绑定到它,并且所有这些都响应触发器。这就是发生在你身上的事情。来,看看这个fiddle我做的。

如何解决

解决此问题的方法是保留对周围视图的引用,以便您可以正确处理它。因此,例如,您可以在路由器中附加对视图的引用,然后这样做,

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();
});

这里我们调用Backbone.View.remove(),它确实在幕后执行this.$el.remove(),有效地移除了我们视图引用的DOM元素并释放了绑定的事件。现在我们的视图可以被垃圾回收了!​​p>

你可以从另一个角度看到我最近是如何回答这个问题的:Saving User Data more than once。如果我不包括 Derick Bailey 关于僵尸视图的开创性文章(我从那里获得了我的大部分信息),我想我会失职,Zombies! RUN! (Managing Page Transitions In Backbone Apps)

【讨论】:

  • 查看与您的问题非常相似的 stackoverflow 问题的链接。它从稍微不同的角度回答了这个问题。
猜你喜欢
  • 1970-01-01
  • 2013-10-14
  • 1970-01-01
  • 2013-07-23
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
相关资源
最近更新 更多