Javascript 主干JS视图渲染未显示

Javascript 主干JS视图渲染未显示,javascript,jquery,backbone.js,Javascript,Jquery,Backbone.js,在下面的代码中,无法呈现“TodoList”。似乎抓取需要时间,因此显示“0”和​​仅在之前 我也不知道为什么后来会显示“3”和“Descriptions”。我只需要在页面中显示“说明列表””。我能够从服务器上获取数据,但不知何故,无法在数据到达时立即显示。请告诉我在下面的代码中需要做什么更改 <html> <head> <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/tw

在下面的代码中,无法呈现“TodoList”。似乎抓取需要时间,因此显示“
0
”和
​​仅在之前

我也不知道为什么后来会显示“
3
”和“
Descriptions
”。我只需要在页面中显示“
说明列表”
”。我能够从服务器上获取数据,但不知何故,无法在数据到达时立即显示。请告诉我在下面的代码中需要做什么更改

<html>
<head>
<link rel="stylesheet"
    href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.1/css/bootstrap.min.css">
</head>

<body>

<div id="demo"></div>

<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>

<script type="text/javascript">

var TodoItem = Backbone.Model.extend({
    urlRoot: 'api',
})

var TodoCollection = Backbone.Collection.extend({
    model: TodoItem,
    url: 'api/todos'
})

var TodoView = Backbone.View.extend({
    template: _.template('<h3> ' +'<input type=checkbox ' +'<% if(status === "complete") print("checked") %>/>' +' <%= description %></h3>'),
    render: function(){
        this.$el.html(this.template(this.model.toJSON()))
    }

})

var TodoListView = Backbone.View.extend({
    initialize: function(){
        this.listenTo(this.collection,'reset',this.render)
        this.collection.fetch({reset:true})
    },
    render: function(){
        console.log(this.collection.length)
        this.collection.forEach(this.addOne,this)
    },
    addOne: function(todoItem){
        console.log(todoItem.get('description'))
        var todoView = new TodoView({model: todoItem})
        this.$el.append(todoView.render())
    }

})


var todoItem = new TodoItem()
var todoList = new TodoCollection()

var todoListView = new TodoListView({el: '#demo', collection: todoList})

todoListView.render()

console.log(todoListView.el)


</script>

</body>

</html>

var TodoItem=Backbone.Model.extend({
urlRoot:'api',
})
var TodoCollection=Backbone.Collection.extend({
型号:TodoItem,
url:'api/todos'
})
var TodoView=Backbone.View.extend({
模板:u.模板(“”+“”+“”),
render:function(){
this.$el.html(this.template(this.model.toJSON()))
}
})
var TodoListView=Backbone.View.extend({
初始化:函数(){
this.listenTo(this.collection,'reset',this.render)
this.collection.fetch({reset:true})
},
render:function(){
console.log(this.collection.length)
this.collection.forEach(this.addOne,this)
},
addOne:函数(todoItem){
console.log(todoItem.get('description'))
var todoView=new todoView({model:todoItem})
此.el.append(todoView.render())
}
})
var todoItem=new todoItem()
var todoList=new TodoCollection()
var todoListView=newtodolistView({el:'#demo',collection:todoList})
todoListView.render()文件
console.log(todoListView.el)
这是我得到的控制台输出:

0 
<div id=​"demo">​</div>​     
3 
pick up cookies
Milk 
Cookies 
0
​​     
3.
捡饼干
牛奶
曲奇饼

对于初学者,您可能希望从获取中取出{reset:true}。 无论如何,获取将自动清除模型/集合

请在命令末尾使用分号,不使用分号会让浏览器解释分号的位置。这需要时间并且容易出错(浏览器可能只是将其放置在您认为不会的位置)

如果这不起作用,您可能希望执行以下操作,将提取添加到渲染中:

render: function(){

    var that = this;

    this.collection.fetch().done(function(data) {

        console.log(that.collection.length);
        that.collection.forEach(that.addOne,that);

    });

},
什么也可能有效,但您需要对此进行测试,我个人总是使用上面的方法:

render: function(){

    this.collection.fetch().done(function(data) {

        console.log(this.collection.length);
        this.collection.forEach(this.addOne,this);

    }, this);

},

我不知道为什么“3”和“Descriptions”后来才显示出来,因为它是异步Ajax请求的结果

现在,尝试更改代码(查看注释):

var TodoView=Backbone.View.extend({
模板:u.模板(“”+“”+“”),
clearItem:function(){
此.$el.find(“h3”).remove();
},
render:function(){
//视图中的所有DOM操作
this.el.append(this.template(this.model.attributes));
归还这个;
}
})
var TodoListView=Backbone.View.extend({
初始化:函数(){
//拆分“重置”事件和“添加”事件
this.listenTo(this.collection,'reset',this.removeAll);
this.listenTo(this.collection,'add',this.addOne);
this.collection.fetch({reset:true});
},
removeAll:function(){
//方法从视图中删除所有元素
//您的问题是,此事件将在ajax请求完成之前触发
日志(“重置!”);
var todoView=new todoView();
todoView.clearItem();
},
addOne:函数(todoItem){
//当集合中的模型更改(获取结果后自动)每个模型时激发。
日志(“添加项:”,todoItem);
var todoView=new todoView({model:todoItem})
todoView.render();
}
});
注意:删除代码中的
todoListView.render()

对不起,我的英语太差了。我没有时间更好地解释。试试我的代码是否有效

  • 主干网中的活动:
  • 获取集合:
  • 渲染视图:

您能添加一个可尝试的示例吗?
我不确定为什么稍后会显示“3”和“说明”
——因为这是异步Ajax请求的结果。尝试更改此:
this.$el.html(this.template(this.model.toJSON())
this.$el.html(this.template(this.model.attributes))
@Frogmouth仍然相同的结果我会收到更多的答复,请……让我们知道这是否是您的正确答案;)您好,我刚刚尝试了上面的代码,我得到的错误是:uncaughttypeerror:cannotread undefinedhey@user3815806的属性'length',我忘了将此传递给函数。请用上面的脚本再试一次!需要使用
reset:true
来获取
fetch
以触发
'reset'
事件,从而触发初始
render
调用。调用
fetch
inside
render
对我来说似乎有点奇怪,调用
this.collection.fetch().done(this.render.bind(this))
inside
initialize
?我不会说它奇怪,这取决于您设置视图的方式。在上面的例子中,他在代码中单独调用渲染。在我看来,这是一个很好的实践,因为你只在需要的时候才渲染。在渲染工作中运行fetch。虽然它确实有点“无结构”。在大多数情况下,您可能会在设置视图后立即运行“渲染”。因此,从初始化中调用渲染是一种很好的做法,也许是最好的做法。不知道,但这可能也会起作用:var todoListView=newtodolistView({el:'#demo',collection:todoList}).done(this.render);
var TodoView = Backbone.View.extend({
    template: _.template('<h3> ' +'<input type=checkbox ' +'<% if(status === "complete") print("checked") %>/>' +' <%= description %></h3>'),
    clearItem : function(){
         this.$el.find("h3").remove();
    },
    render: function(){
        //all DOM manipulation in view
        this.$el.append(this.template(this.model.attributes));
        return this;
    }

})

var TodoListView = Backbone.View.extend({
    initialize: function(){
        // split "reset" event and "add" event
        this.listenTo(this.collection,'reset',this.removeAll);
        this.listenTo(this.collection,'add',this.addOne);
        this.collection.fetch({reset:true});
    },

    removeAll : function(){
        //method to remove all element from view
        //your problem is that this event will fire before ajax request done
        console.log("reset!");
        var todoView = new TodoView();
        todoView.clearItem();
    },

    addOne: function(todoItem){
        //fire when a model in the collection change (automatic after fetch result) for each model.
        console.log("add ITEM:",todoItem);
        var todoView = new TodoView({model: todoItem})
        todoView.render();
    }

});