【问题标题】:Backbone.js and FormDataBackbone.js 和 FormData
【发布时间】:2013-01-22 12:33:22
【问题描述】:

有什么方法可以使用 Backbone.js 和它的模型架构,我可以将 formdata 对象发送到服务器?我遇到的问题是 Backbone 发送的所有内容都被编码为 JSON,因此 formdata 对象没有正确发送(显然)。

我正在通过直接的 jQuery ajax 请求并将 formdata 对象作为数据属性来临时解决这个问题,但这并不理想。

【问题讨论】:

  • 您可以全局、按模型或按集合覆盖sync,以任何您想要的方式与服务器通信。
  • 嘿,你的建议是我采用的方法。随意提交作为答案,我会批准它。

标签: javascript json html backbone.js form-data


【解决方案1】:

这是通过覆盖sync 方法的解决方案,我用它来允许文件上传。

在这种情况下,我会覆盖模型的 sync 方法,但这也可以是 Backbone.sync 方法。

var FileModel = Backbone.Model.extend({

  urlRoot: CMS_ADMIN_URL + '/config/files',

  sync: function(method, model, options){

    // Post data as FormData object on create to allow file upload
    if(method == 'create'){
      var formData = new FormData();

      // Loop over model attributes and append to formData
      _.each(model.attributes, function(value, key){
        formData.append(key, value);
      });

      // Set processData and contentType to false so data is sent as FormData
      _.defaults(options || (options = {}), {
        data: formData,
        processData: false,
        contentType: false
      });
    }
    return Backbone.sync.call(this, method, model, options);
  }
});

编辑:

要跟踪上传进度,您可以在选项中添加xhr 选项:

...

_.defaults(options || (options = {}), {
  data: formData,
  processData: false,
  contentType: false
  xhr: function(){
    // get the native XmlHttpRequest object
    var xhr = $.ajaxSettings.xhr();
    // set the onprogress event handler
    xhr.upload.onprogress = function(event) {
      if (event.lengthComputable) {
        console.log('%d%', (event.loaded / event.total) * 100);
        // Trigger progress event on model for view updates
        model.trigger('progress', (event.loaded / event.total) * 100);
      }
    };
    // set the onload event handler
    xhr.upload.onload = function(){
      console.log('complete');
      model.trigger('progress', 100);
    };
    // return the customized object
    return xhr;
  }
});

...

【讨论】:

  • 这是一个很好的答案,IMO 在这个页面上是最好的。处理服务器通信的正确方法是在模型级别编辑同步方法,但它不是 i> 需要对其进行广泛的猴子补丁:只需编辑选项哈希(保存数据和 xhr 选项),就完成了。
【解决方案2】:

只是为这个问题添加一个答案,这就是我如何去做而不必覆盖sync

在我看来,我有类似的东西:

$('#' + $(e.currentTarget).data('fileTarget')).trigger('click').unbind('change').bind('change', function(){
    var form_data = new FormData();
    form_data.append('file', $(this)[0].files[0]);
    appManager.trigger('user:picture:change', form_data);
});

然后触发控制器中执行此操作的函数:

var picture_entity = new appManager.Entities.ProfilePicture();
picture_entity.save(null, {
    data: data,
    contentType: false,
    processData: false,
});

此时,我将使用我的 FormData 对象覆盖 jQuery 的 data

【讨论】:

    【解决方案3】:

    我有类似的要求,这就是我所做的:

    在视图中:

    var HomeView = Backbone.View.extend({
        el: "#template_loader",
        initialize: function () {
            console.log('Home View Initialized');
        },
        render: function () {
            var inputData = {
                cId: cId,
                latitude: latitude,
                longitude: longitude
            };
    
            var data = new FormData();
    
            data.append('data', JSON.stringify(inputData));
    
            that.model.save(data, {
                data: data,
                processData: false,
                cache: false,
                contentType: false,
                success: function (model, result) {
                    alert("Success");
                },
                error: function () {
                    alert("Error");
                }
            });
        }
    });    
    

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      我有同样的问题。您可以在上面看到我解决它的方式。

      var $form = $("myFormSelector");
      
      //==> GET MODEL FROM FORM
      var model = new MyBackboneModel();
      var myData = null;
      var ajaxOptions = {};
      // Check if it is a multipart request.
      if ($form.hasFile()) {
          myData = new FormData($form[0]);
          ajaxOptions = {
              type: "POST",
              data: myData,
              processData: false,
              cache: false,
              contentType: false
          };
      } else {
          myData = $form.serializeObject();
      }
      
      // Save the model.
      model.save(myData, $.extend({}, ajaxOptions, {
          success: function(model, data, response) {
              //==> INSERT SUCCESS
          },
          error: function(model, response) {
              //==> INSERT ERROR
          }
      }));
      

      hasFile 是扩展 JQuery 函数的自定义方法。

      $.fn.hasFile = function() {
          if ($.type(this) === "undefined")
              return false;
      
          var hasFile = false;
          $.each($(this).find(":file"), function(key, input) {
              if ($(input).val().length > 0) {
                  hasFile = true;
              }
          });
      
          return hasFile;
      };
      

      【讨论】:

        【解决方案5】:

        只需使用Backbone.emulateJSON = true;:http://backbonejs.org/#Sync-emulateJSON

        将导致 JSON 在模型参数下被序列化,并使用 application/x-www-form-urlencoded MIME 类型发出请求,就像来自 HTML 表单一样。

        【讨论】:

        • 但这会将 JSON 序列化为字符串,并像对象一样显示为字符串。
        • 创建formData对象并发送给服务器
        【解决方案6】:

        没有一个答案对我有用,以下是简单易行的解决方案。通过像这样覆盖sync 方法和options.contentType

        sync: function(method, model, options) {
            options = _.extend({
                contentType : 'application/x-www-form-urlencoded;charset=UTF-8'
            }, options);
        
            options.data = jQuery.param(model.toJSON());
        
            return Backbone.sync.call(this, method, model, options);
        }
        

        【讨论】:

          【解决方案7】:

          一个简单的,希望这会对某人有所帮助。

          1. 创建一个Backbone Model的对象:

            var importModel = new ImportModel();
            
          2. 调用Backbone Model的Save[POST]方法并传递FormData对象。

            var objFormData = new FormData();
            objFormData.append('userfile', files[0]);
            
            importModel.save(objFormData, {
             contentType: false, 
             data: objFormData, 
             processData: false,
             success: function(data, status, xhr) { },
             error: function(xhr, statusStr) { }
            });
            

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-11-02
            • 2012-03-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多