样板集合视图不更新?

时间:2013-07-24 02:31:57

标签: backbone.js backbone-views backbone-routing

我使用yeoman generator-bbb在我的网站上创建了一个小应用程序。问题是集合视图不会更新。

这是主要代码: app.js:

define(function(require, exports, module) {

    // External dependencies.
    var _ = require("underscore");
    var $ = require("jquery");
    require("modernizr");
    var Backbone = require("backbone");
    var LayoutManager = require("backbone.layoutmanager");
    require("plugins/backbone.collectioncache");
    require("bootstrap-jam");
    var app = module.exports = {};

    // Path Backbone fetching to emmit a "fetch" event
    Backbone.Collection.prototype.fetch = function() {
        var fetch = Backbone.Collection.prototype.fetch;

        return function() {
            this.trigger("fetch");
            return fetch.apply(this, arguments);
        };
    }();

    // The root path to run the application through.
    app.root = "/";

    // Configure LayoutManager with Backbone Boilerplate defaults.
    LayoutManager.configure({
        // Allow LayoutManager to augment Backbone.View.prototype.
        manage: true,

        // Indicate where templates are stored.
        prefix: "app/templates/",

        // This custom fetch method will load pre-compiled templates or fetch them
        // remotely with AJAX.
        fetch: function(path) {
            // Concatenate the file extension.
            path = path + ".html";

            // If cached, use the compiled template.
            if (window.JST && window.JST[path]) {
                return window.JST[path];
            }

            // Put fetch into `async-mode`.
            var done = this.async();

            // Seek out the template asynchronously.
            $.get(app.root + path, function(contents) {
                done(_.template(contents));
            }, "text");
        }
    });

    // The application user interface handles link hijacking and can be modified
    // to handle other application global actions as well.
    app.ui = new Backbone.View({
        el: "#layout",

        template: "main-layout",

        events: {
            "click a[href]:not([data-bypass])": "hijackLinks"
        },

        hijackLinks: function(ev) {
            // Get the absolute anchor href.
            var $link = $(ev.currentTarget);
            var href = {
                prop: $link.prop("href"),
                attr: $link.attr("href")
            };
            // Get the absolute root.
            var root = location.protocol + "//" + location.host + app.root;

            // Ensure the root is part of the anchor href, meaning it's relative.
            if (href.prop.slice(0, root.length) === root) {
                // Stop the default event to ensure the link will not cause a page
                // refresh.
                ev.preventDefault();

                // `Backbone.history.navigate` is sufficient for all Routers and will
                // trigger the correct events. The Router's internal `navigate` method
                // calls this anyways.  The fragment is sliced from the root.
                Backbone.history.navigate(href.attr, true);
            }
        }
    });
});

router.js

define(function(require, exports, module) {

    var app = require("app");
    var Music = require("modules/music");

    // Defining the application router.
    module.exports = Backbone.Router.extend({
        initialize: function() {
            var collections = {
                musics: new Music.Collection()
            };

            _.extend(this, collections);    

            app.ui.setViews({
                ".musics": new Music.Views.List(collections)
            }).render();
        },

        routes: {
            "": "index",
            "tag/:name": "tag"
        },

        index: function() {
            this.reset();
        },

        tag: function(name) {
            this.reset();

            this.musics.tag = name;
            this.musics.fetch();
        },

        reset: function() {
            if (this.musics.length) {
                this.musics.reset();
            }
        },

        go: function() {
            return this.navigate(_.toArray(arguments).join("/"), true);
        }
    });
});

music.js:

define(function(require, exports, module) {

    // music module dependedn on app
    var app = require("app"),
        Music = module.exports = {};

    Music.Collection = Backbone.Collection.extend({

        url: function() {
            return "https://api.douban.com/v2/music/search?tag=" + encodeURIComponent(this.tag) + "&callback=?";
        },

        cache: true,

        parse: function(res) {
            if ( res.musics.length ) {
                this.status = "valid";
                return res.musics;
            }

            this.status = "invalid";
            return res;
        },

        initialize: function(models, options) {
            if (options) {
                this.tag = options.tag;
            }
        }
    });

    Music.Views = {};
    // set the list view
    Music.Views.List = Backbone.View.extend({

        template: "music/list",

        serialize: function() {
            return { collection: this.options.musics };
        },

        events: {
            "submit form": "updateMusic"
        },

        updateMusic: function() {
            app.router.go( "tag", this.$('form').find('input').val() );
            return false;
        },

        beforeRender: function() {
            this.options.musics.each(function(music) {
                this.insertView("ul", new Music.Views.Item({
                    model: music
                }));
            }, this);
        },

        afterRender: function() {
            this.$("input.invalid").focus();
        },

        initialize: function() {
            this.listenTo(this.options.musics, {
                "reset": this.render,

                "fetch": function() {
                    this.$("ul").parent().html("搜索中请稍候......");
                }
            });
        }
    });

    // set the item view
    Music.Views.Item = Backbone.View.extend({

        template: "music/item",

        tagName: "li",

        serialize: function() {
            return { model: this.model };
        },

        initialize: function() {
            this.listenTo( this.model, "change", this.render() );
        }
    });
});

1 个答案:

答案 0 :(得分:0)

看起来您正在提出跨域请求。您已设置url,以便接受回调。现在无处允许Backbone知道这是jsonp请求。

尝试将dataType: 'jsonp'属性传递给获取请求。

tag: function(name) {
        this.reset();

        this.musics.tag = name;
        this.musics.fetch({
            dataType : 'jsonp'
        });
    },

而且我也没有看到在你所指的

视图中的任何地方定义的2个方法
"reset": this.render,

this.insertView("ul",