具有服务器端呈现的HTML片段的主干模型

Backbone model with server-side rendered HTML snippet

本文关键字:片段 模型 HTML 服务器端      更新时间:2023-09-26

我想开始使用Backbone.js来更好地构建我的JavaScript文件。然而,我不想重做我的应用程序,只通过API输出JSON。如果我错了,请纠正我的错误,但到目前为止,我的印象是,即使没有JSON API,我仍然可以使用Backbone.js。现在我遇到了一个问题,我的服务器返回HTML,而Backbone模型不喜欢这样,并返回了一个错误。

基本上,我想根据类别加载一个HTML片段:

var Filter = Backbone.Model.extend({
    url: '/filters/',
});
var FilterView = Backbone.View.extend({
    initialize: function() {    
        this.model.on('change', this.updateFilter, this);
        this.changeFilter();
    },
    changeFilter: function() {
        this.model.fetch({data: $.param({category: this.options.category})});
    },
    updateFilter: function(filters) {
        console.log(filters);
        this.$el.html(filters);
    },
});
var filter = new Filter();
var filterView = new FilterView({
    el: $( '#filterContainer' ),
    category: $( '#categorySlug' ).data( 'slug' ),
    model: filter,
});

现在我想我可以使用这个简单的模型来通过Ajax检索我的HTML片段。请求正确激发,但Backbone返回一个错误,并且updateFilter从未被调用。

我没有得到什么吗?我需要更改什么才能使它与HTML而不是JSON响应一起工作?或者我根本不应该使用模型?

您需要扩展您的Backbone模型来覆盖fetch,以便与来自lost的答案一样,您需要将数据类型传递给Backbone。同步

fetch: function(options) {
    return Backbone.Model.prototype.fetch.call(this, _.extend({ dataType: "html"}, options));
}

这并不是Backbone的实际操作方式,但您可以通过在模型中包含适当的parse函数将内容填充到模型字段中(称为snippet):

var Filter = Backbone.Model.extend({
  url: '/filters/',
  parse: function (response) {
    return {
      snippet: $(response)
    }
  }
});

同样,在这里,您有点超出了Backbone的自然顺序,但现在您应该能够使用常见的fetch()get()set()方法来管理模型的内容。例如,

// in view:
updateFilter: function (filter) {
    this.$el.html(filter.get('snippet'));
},
// etc..

在我看来,问题在于请求的accept标头默认包含application/json,这会触发错误。您可以通过执行model.fetch({ dataType : 'html'})来调整accept标头。这个问题的公认答案是:Backbone.js带参数的fetch帮助我找到了答案。

我认为这个问题的答案是,您需要将主干模型的同步方法替换为一个可以使用HTML的方法。以下代码生成的模型的数据在"snippet"值中:

sync: function (method, model, options) {
    // NOTE: This generic function won't work for pushing changes
    if (method !== 'read') {
        console.log('Cannot update html model');
        return false;
    }
    // As we're only reading default type to GET - see Backbone.sync
    // for a more generic way of doing this.
    var params = _.extend({ type: 'GET',
        contentType: 'application/xml',
        dataType: 'text'
    });
    var urlError = function () {
        throw new Error('A "url" property or function must be specified');
    };
    // ensure that we have a URL
    if (!params.url) {
        params.url = _.result(model, 'url') || urlError();
    }
    // NOTE: If you extend this function to deal with creates you'll need to ensure
    // params.data is set and make sure that the data isn't processed.
    // See the Backbone.sync methods for more info
    // Finally wrap the backbone success callback to plonk the data in snippet field of an object
    var origSuccess = options.success;
    options.success = function (data, textStatus, xhr) {
        origSuccess({ snippet: data }, textStatus, xhr);
    };
    // Make the request, allowing the user to override any Ajax options.
    var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
    model.trigger('request', model, xhr, options);
    // make the request
    return xhr;
}

标准的主干阅读功能应该只在下面工作。编写的会失败,但您可以随时扩展函数来处理这些问题。

这个问题有点老,但我在git上发现了一个项目,该项目描述了一种非常好的更新模型的方法,即在项目服务器端循环,并在页面呈现时将它们添加到集合中。

https://github.com/runemadsen/Backbone-With-Server-Side-Rendering/blob/master/views/modeltest.erb