骨干视图无法正确更新

时间:2012-12-31 21:04:24

标签: javascript backbone.js

我想显示一个列表,一旦点击列表中的项目,我希望隐藏列表,并检索并显示项目的详细信息。

点击鼠标,从REST Web服务检索详细信息,并隐藏项目列表。问题是在刷新页面之前不会显示项目详细信息。我不太明白我做错了什么。

以下是我的代码示例:

<html>
<head>
    <title>Backbone Test</title>
    <script type="text/javascript" src="js/lib/jquery-1.7.1-min.js"></script>
    <script type="text/javascript" src="js/lib/underscore-min.js"></script>
    <script type="text/javascript" src="js/lib/backbone-min.js"></script>
</head>

<body>

<div>VIN Search List:</div>
<div id="item-list" />
<div id="item-details" />

<script type="text/javascript">
$(function() 
{
    var Item = Backbone.Model.extend({
        urlRoot: "rest/search",
        defaults: {
            "uid": ""
        }
    });    

    var Items = Backbone.Collection.extend({
        model: Item,
        url: "rest/search/", 
    });

    var ItemDetail = Backbone.Model.extend({
        urlRoot: "rest/search/details",
        defaults: {
            "uid": "",
            "details": ""
        },

        url : function() {
            return this.id ? this.urlRoot + '/' + this.id : this.urlRoot;
        } 
    });    

    var ListView = Backbone.View.extend(
    {
        tagName: "ol",

        initialize: function() 
        {
            _.bindAll(this, 'render');
            this.model.bind("destroy", this.close, this);
        },

        render: function() 
        {
            _.each(this.model.models, function(uid) {
                $(this.el).append( new ItemView({model:uid}).render().el );
            }, this);  
            return this;
        },

        close: function() 
        {
            $(this.el).unbind();
            $(this.el).remove();
        },
    });

    var ItemView = Backbone.View.extend(
    {
        tagName: "li",

        template: _.template("<%= uid %>"),

        events: { "click": "showDetails" },

        initialize: function() 
        {
            _.bindAll(this, 'render');
            this.model.bind("change", this.render, this);
            this.model.bind("destroy", this.close, this);
        },

        render: function(eventName) 
        {
            $(this.el).html( this.template( this.model.toJSON() ) );
            return this;
        },

        close: function() 
        {
            $(this.el).unbind();
            $(this.el).remove();
        },

        showDetails: function() 
        {
            app.navigate("details/" + this.model.get("uid"), {trigger: true});
            return false;
        },
    });

    var DetailsView = Backbone.View.extend(
    {
        tagName: "ul",

        template: _.template("<li><%= uid %></li><li><%= details %></li>"),

        initialize: function() 
        {
            _.bindAll(this, 'render');
            this.model.bind("change", this.render, this);
            this.model.bind("destroy", this.close, this);
        },

        render: function(eventName) 
        {
            $(this.el).html( this.template( this.model.toJSON() ) );
            return this;
        },

        close: function() 
        {
            $(this.el).unbind();
            $(this.el).remove();
        },
    });

    var AppRouter = Backbone.Router.extend({

        routes:
        {
            "": "list",
            "details/:uid": "Details"
        },

        list: function() 
        {
            var self = this;
            this.itemList = new Items();
            this.itemList.fetch(
            {
                success: function() 
                {
                    self.listView = new ListView({model: self.itemList});
                    $('#item-list').html( self.listView.render().el );
                }
            });
        },

        Details: function(uid) 
        {
            if (this.lListView) this.listView.close();

            var self = this;
            this.details = new ItemDetail({id: uid});
            this.details.fetch(
            {
                success: function() 
                {
                    self.detailsView = new DetailsView({model: self.details});
                    $('#item-details').html( self.detailsView.render().el );
                }
            });
        },

    });

    // Start up
    var app = new AppRouter();
    Backbone.history.start();
});
</script>

1 个答案:

答案 0 :(得分:0)

如果我更改详细信息路由以修改#item-list而不是#item-details,则一切都会正常运行。

我猜测,因为#item-list是最初在默认路由中修改过的元素,所以我无法修改位于其外部的元素是heirarchy?我真的很想了解这种行为。

Blargh。看起来我只需要手动切换#item-details元素的显示来强制渲染元素。我仍然不确定为什么默认路由的行为不同,但这不是一个大问题。

        this.details.fetch(
        {
            success: function() 
            {
                self.detailsView = new DetailsView({model: self.details});
                $('#item-details').html( self.detailsView.render().el );
                $('#item-details').css( "display", "block" ); // FORCE DISPLAY
            }
        });