Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/427.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript BackboneJS渲染问题_Javascript_Jquery_Node.js_Backbone.js_Coffeescript - Fatal编程技术网

Javascript BackboneJS渲染问题

Javascript BackboneJS渲染问题,javascript,jquery,node.js,backbone.js,coffeescript,Javascript,Jquery,Node.js,Backbone.js,Coffeescript,在过去的六个月里,我一直在用脊梁骨工作。前两个月,我一直在胡思乱想,学习并弄明白如何围绕它构建代码。在接下来的4个月里,一个适合生产的应用程序被大量使用。不要误解我的意思,主干将我从以前标准的数千行混乱的客户端代码中解救出来,但它使我能够在更短的时间内完成更宏大的事情,带来了一系列全新的问题。对于我在这里提出的所有问题,有一些简单的解决方案,感觉像是黑客,或者只是感觉错了。我保证一个很棒的解决方案会得到300分的奖励。下面是: 加载-对于我们的用例(管理面板),悲观同步是不好的。对于某些事情,我

在过去的六个月里,我一直在用脊梁骨工作。前两个月,我一直在胡思乱想,学习并弄明白如何围绕它构建代码。在接下来的4个月里,一个适合生产的应用程序被大量使用。不要误解我的意思,主干将我从以前标准的数千行混乱的客户端代码中解救出来,但它使我能够在更短的时间内完成更宏大的事情,带来了一系列全新的问题。对于我在这里提出的所有问题,有一些简单的解决方案,感觉像是黑客,或者只是感觉错了。我保证一个很棒的解决方案会得到300分的奖励。下面是:

  • 加载-对于我们的用例(管理面板),悲观同步是不好的。对于某些事情,我需要在接受它们之前在服务器上验证它们。我们是在“同步”事件合并到主干网之前开始的
  • 我们用这个小代码来模拟加载事件:

    window.old_sync = Backbone.sync
    
    # Add a loading event to backbone.sync
    Backbone.sync = (method, model, options) ->
      old_sync(method, model, options)
      model.trigger("loading")
    
    太好了。它按预期工作,但感觉不正确。我们将此事件绑定到所有相关视图,并显示加载图标,直到从该模型接收到成功或错误事件。有更好、更理智的方法吗

    现在,对于那些困难的人:

  • 太多的东西呈现了太多的内容-假设我们的应用程序有选项卡。每个选项卡控制一个集合。在左边你可以看到收藏。单击模型以在中心开始编辑它。您可以更改其名称,然后按tab键进入下一个表单项。现在,您的应用程序是一个“实时的东西”,它可以注意到差异,运行验证,并自动将更改同步到服务器,无需保存按钮!很好,但是表单开头的H2与输入中的名称相同-您需要更新它。哦,你需要把名单上的名字更新到旁边。哦,而且名单是按名字排序的 下面是另一个示例:您希望在集合中创建一个新项。你按下“新建”按钮,开始填写表格。是否立即将项目添加到集合中?但是如果你决定放弃它会发生什么呢?或者如果您将整个集合保存在另一个选项卡上?此外,还有一个文件上传-您需要先保存并同步模型,然后才能开始上传文件(以便将文件附加到模型)。因此,所有内容都会在抖动中开始渲染:保存模型和列表,表单会再次进行渲染-现在已同步,因此会出现一个新的删除按钮,并显示在列表中-但现在文件上载完成上载,所有内容都会再次开始渲染

    将子视图添加到组合中,所有内容都开始看起来像Fellini电影

  • 一路向下都是子视图。出于对一切神圣事物的热爱,我无法找到一种正确的方法将jQuery插件或DOM事件附加到任何具有子视图的视图。地狱接踵而至。工具提示会听到渲染持续很长时间,并开始出现异常,子视图会变成僵尸或不响应。这是主要的痛点,就像这里实际的bug一样,但我仍然没有一个包罗万象的解决方案

  • 闪烁-渲染速度很快。事实上,它是如此之快,以至于我的屏幕看起来像是癫痫发作。有时需要再次加载图像(通过另一个服务器调用!),因此html会突然最小化,然后再次最大化-该元素的css宽度+高度将解决这一问题。有时候我们可以用fadeIn和fadeOut来解决这个问题,这是一个让人头疼的问题,因为有时候我们重用一个视图,有时候又重新创建它

  • TL;DR-我的主干中的视图和子视图有问题-它渲染太多次,渲染时闪烁,子视图分离我的DOM事件并吞噬我的大脑

    谢谢大家!

    更多细节:带有Ruby on Rails Gem的BackboneJS。使用下划线的模板

    视图的部分渲染 为了最小化DOM层次结构的完整呈现,可以在DOM中设置特殊节点,以反映给定属性的更新

    让我们使用这个简单的下划线模板,一个名称列表:

    • :
    注意类
    模型--name
    ,这将是我们的注入点

    然后,我们可以定义一个基本视图(或修改Backbone.view),以便在更新这些节点时使用适当的值填充它们:

    var V=Backbone.View.extend({
    初始化:函数(){
    //将所有更改绑定到集合中的模型
    this.collection.on('change',this.autoupdate,this);
    },
    //抓取更改并填充任何区域集以接收值
    自动更新:功能(模型){
    var_this=这个,
    changes=model.changedAttributes(),
    属性=\键(更改);
    _.每个(属性,函数(属性){
    _这个.$('.model-'+model.cid+'-'+attr.html(model.get(attr));
    });
    },
    //呈现完整的模板
    //只有当视图真正发生戏剧性变化时才应该发生
    渲染:函数(){
    var数据,html;
    //生成数据以呈现模板
    //实际上,添加了cid的.collection.toJSON()
    data=this.collection.map(函数(模型){
    返回u2;.extend(model.toJSON(),{cid:model.cid});
    });
    html=模板({子项:数据});
    这个.$el.html(html);
    归还这个;
    }
    });
    
    代码会有所不同,以适应模型而不是集合。 小提琴

    限制DOM操作 将呈现委托给子视图可能代价高昂,它们的HTML片段必须插入父视图的DOM中。 看看这个

    其要点是,生成完整的HTML结构并应用视图要比构建视图和子视图快得多
    //Container view
    init: function() {
        this.collection = new Backbone.Collection({
            url: 'http://mybestpage.com/collection'
        });
        this.collection.bind('change', this.render, this);
        this.collection.fetch();
    },
    render: function() {
    
        _.each(this.collection.models, function(model) {
             var newView = new myItemView({
                  model: model,
                  name: 'view' + model.id
             });
             this.$('#my-collection').append(newView.render().$el);
             view.on('viewEdit', this.displayValue);
        }, this);
    },
    ...
    displayValue: function(value) {
        //method 1
        this.displayView.setText(value); //we can create little inner view before, 
                                         //for text displaying. Сonvenient at times.
        this.displayView.render();
        //method 2
        $(this.el).find('#display').html(value);
    }
    
    //View from collection
    myItemView = Backbone.View.extend({
    events: {
        'click #edit': 'edit'
    },
    init: function(options) {
        this.name = options.name;
    },
    ...
    edit: function() {
        this.trigger('viewEdit', this.name, this);
    }
    
    var smartView = Backbone.View.extend({
      initialize: function(){
        this.model.on( "imageUpdate", this.imageUpdate, this );
        this.model.on( "contentUpdate", this.contentUpdate, this );
      },
    
      render: function(){
        this.$el.html(this.template(this.model.toJSON()));
      },
    
      imageUpdate: function(){
        this.$el.find('#image').attr('src', this.model.get('imageUrl'));
      },
      contentUpdate: function(){
        this.$el.find('#content').html(this.model.get('content'));
      }
    })
    
    Organization model
    |--> Event model
    |--> News model
       |--> Comment model