【问题标题】:Backbone model.get('key') undefined after .fetch() call, even inside success callback.fetch() 调用后的主干模型.get('key') 未定义,即使在成功回调中也是如此
【发布时间】:2015-10-27 13:43:41
【问题描述】:

我是 Backbone.js 的新手,刚刚完成了创建“用户列表”系统 (https://www.youtube.com/watch?v=FZSjvWtUxYk) 的基本教程,其中所有模板、脚本等都是内联创建的。我让一切工作起来都很容易,所以我决定尝试模块化,因为我知道这是最好的做法。我正在遵循 AMD 方法 (https://cdnjs.com/libraries/backbone.js/tutorials/organizing-backbone-using-modules) 的本指南,除了一件事外,一切都正常工作 - 编辑用户时,“当前”数据没有加载到表单中。到目前为止,我在 SO 和其他地方发现的所有问题都已通过将模板生成代码放入 success: 回调 .fetch() 调用中来解决,但我已经这样做了。

代码如下:

(我忽略了处理 require.js 配置、路由器初始化等的 main.js 和 app.js。它们似乎工作得很好。)

// Filename: router.js
define([
  'jquery',
  'underscore',
  'backbone',
  'views/userList',
  'views/editUser'
], function($, _, Backbone, UserListView, EditUserView){
  var AppRouter = Backbone.Router.extend({
    routes: {
      '': 'home',
      'new': 'editUser',
      'edit/:id': 'editUser'
    }
  });

  var initialize = function(){
    var app_router = new AppRouter;

    app_router.on('route:home', function(){
      var userListView = new UserListView();

      userListView.render();
    });

    app_router.on('route:editUser', function(id) {
      var editUserView = new EditUserView();

      editUserView.render({ id: id });
    });

    Backbone.history.start();
  };

  return {
    initialize: initialize
  };
});

views/editUser.js

// Filename: views/editUser
define([
  'jquery',
  'underscore',
  'backbone',
  'models/user',
  'text!/templates/editUser.html'
], function($, _, Backbone, UserModel, rawEditUserTemplate) {
  var userListView = Backbone.View.extend({
    // Element to use for this view
    el: $('.page'),

    // Function to call when this view is rendered
    render: function(options) {
      var that = this;

      // If there is an ID, we are editing
      if ( options.id ) {
        // Create the user, passing the ID
        that.editUser = new UserModel({ id: options.id });

        // Fetch the user data
        that.editUser.fetch({
          // When the fetch is returned
          success: function(userData) {
            // Generate the template and pass the data in
            var editUserTemplate = _.template( rawEditUserTemplate );
            that.$el.html(editUserTemplate({ user: userData }));
          }
        })
      }
      else { // We are creating a new user
        // Generate the template with an empty user
        var editUserTemplate = _.template( rawEditUserTemplate );
        this.$el.html(editUserTemplate({ user: null }));
      }
    },
    events: {
      'submit .edit-user-form': 'saveUser',
      'click .delete': 'deleteUser'
    },
    saveUser: function(e) {
      e.preventDefault();

      // Get the details
      var userDetails = $(e.currentTarget).serializeObject();

      // Create a user model
      var user = new UserModel();

      // Save the user details
      user.save(userDetails, {
        success: function(user) {
          Backbone.history.navigate('', { trigger: true });
        }
      });
    },
    deleteUser: function(e) {
      e.preventDefault();

      // Destroy the user we are editing
      this.editUser.destroy({
        // When the destroy is finished
        success: function() {
          // Back to home
          Backbone.history.navigate('', { trigger: true });
        }
      });
    }
  });

  // Our module now returns our view
  return userListView;
});

模板/editUser.html

<form class="edit-user-form">
  <legend><%= user ? 'Update' : 'Create' %> User</legend>

  <div class="form-group">
    <label for="firstname">First Name</label>
    <input type="text" class="form-control" name="firstname" id="firstname" value="<%= user ? user.get('firstname') : '' %>" />
  </div>

  <div class="form-group">
    <label for="lastname">Last Name</label>
    <input type="text" class="form-control" name="lastname" id="lastname" value="<%= user ? user.get('lastname') : '' %>" />
  </div>

  <div class="form-group">
    <label for="age">Age</label>
    <input type="text" class="form-control" name="age" id="age" value="<%= user ? user.get('age') : '' %>" />
  </div>

  <hr />

  <button class="btn btn-success" type="submit"><%= user ? 'Update' : 'Create' %></button>

  <% if ( user ) { %>
  <input type="hidden" name="id" id="id" value="<%= user.id %>" />
  <button class="btn btn-danger delete">Delete</button>
  <% }; %>
</form>

使用此代码,无论我是在编辑还是创建,我都会得到一个空白的编辑表单,但是模板中的“创建”与“更新”文本开关工作正常。这意味着实际上正在传递一个用户对象,当我将 console.log(user) 添加到模板文件中时,它实际上是在向我显示用户数据。但是,当我记录 user.get('firstname') 或任何其他属性时,它会记录“未定义”。

【问题讨论】:

  • 乍一看,它看起来很适合我。您确定返回的 JSON 响应包含属性吗?如果在成功回调中使用 console.log(userData.attributes) 会看到什么?
  • 这是它记录的内容:i.imgur.com/wye24pA.png 这是正确的数据
  • 不,那不是正确的数据。那是一个有 2 个键的对象:“0”和“id”,所有的属性都放在带有“0”键的对象中。您的响应 JSON 错误。
  • 对不起,我的意思是实际的用户信息是正确的。所以你是说 API 给我的数据格式不正确?
  • 是的。您的实际响应是一个带有 2 个键(“0”和“id”)的对象,但您需要一个带有“id”、“age”、“firstname”、“lastname”键的响应。

标签: javascript jquery backbone.js


【解决方案1】:

问题出在我的用户模型中,我没有在上面包含它,因为我当时不明白为什么它可能是相关的。

我将其定义为:

var userModel = Backbone.Model.extend({
  url: '/users'
});

应该是什么时候:

var userModel = Backbone.Model.extend({
  urlRoot: '/users'
});

错误的选项导致 API 返回集合而不是模型,因此 .get() 无法正常工作。

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    相关资源
    最近更新 更多