【问题标题】:Flickering Backbone views - callbacks for render methods?闪烁的主干视图 - 渲染方法的回调?
【发布时间】:2015-06-25 23:06:02
【问题描述】:

我遇到的问题是我的父视图的 render() 方法在其子 render() 方法完成之前返回。

所以我在主干路由器中有这些调用:

       this.viewState.get('headerView').render();
       this.viewState.get('mainView').render();
       this.viewState.get('footerView').render(); //this function starts (and completes) before the above completes

问题是页脚在 mainView 渲染之前渲染,因为在 mainView 的子视图完成渲染到 DOM 之前,主视图 render() 函数完全返回。因此,当页脚插入 DOM 时屏幕会闪烁,然后当 mainView 实际呈现时,页脚会被向下推。

我喜欢 Backbone 视图的 render() 函数中“返回这个”的范例,但我能想到的解决这个问题的唯一方法是使用异步库或其他东西链接 render() 函数,使用异步/CPS 回调。

所以,我将这段代码作为我的主干视图渲染函数的一部分:

//这里父渲染它的子视图:

  function renderChildren($template) {
                    var ret = EJS.render($template, {
                        users: data
                    });

                    this.$el.html(ret); //***

                    this.childLoginView = new LoginView({el: this.$('#child-view-login-container')});
                    //console.log('this.childLoginView.$el', self.childLoginView.$el);
                    this.childLoginView.render();
                    this.childLoginView.delegateEvents();

                    this.childRegisteredUsersView = new RegisteredUsersView({el: this.$('#child-view-registered-users-container')});
                    //console.log('this.childRegisteredUsersView.$el', self.childRegisteredUsersView.$el);
                    this.childRegisteredUsersView.render();
                    this.childRegisteredUsersView.delegateEvents();

                    console.log('IndexView rendered');
                }

我可以告诉你一个事实,即在子视图实际呈现之前记录了“IndexView 呈现”。这当然意味着子渲染函数是异步的,也意味着网页闪烁,因为子视图仅在父视图的渲染方法完成后才渲染。

就像我说的,这表明 render() 方法确实是异步的。所以我想一次渲染一个视图,这样页面就不会闪烁——这是一件合理的事情吗?希望 Web 视图上的闪烁会减少,因为事物只是按顺序呈现的,但我还不确定如何做到这一点。

关于带***的行。有没有办法为父视图定义模板,只有在子视图渲染后,才用.html()将模板插入DOM?这可能需要回调,在这种情况下,不可能从父视图的 render() 函数中“返回 this”。

【问题讨论】:

    标签: javascript jquery backbone.js


    【解决方案1】:

    您的 view.render() 中可能有一些异步操作,这会导致竞争条件。

    使用$.Deferred();:

    render: function () {
        var self = this,
            dfd = $.Deferred();
        this.model.fetch({
            succcess: function (response) {
              // do here the operations on your cached DOM:
              self.$el.append(response.model.models);
              dfd.resolve({template: self.$el});
            }
        });
        return dfd.promise();
    }
    

    现在你可以控制渲染方法的顺序了:

    $.when(viewState.get('headerView').render()).then(function(result) {
        $('body').append(result.template);
        viewState.get('mainView').render().then(function (result) {
            $('body').append(result.template);
        });
    });
    

    这将一次渲染一件。随着 promise 的解决,用户将看到屏幕上出现的新部分。

    看到这个小提琴:https://jsfiddle.net/h0h888rm/2/

    如果您想等到每次渲染完成并仅重新加载一次父视图,请考虑以下替代解决方案:

    替代方案:

    如果您希望渲染异步运行,但仅在所有渲染完成后才进行 parentView 渲染,请执行以下操作:

    $.when(
        viewState.get('headerView').render(),
        viewState.get('mainView').render()
    ).then(function (result1, result2) {
        $('body').append(result1.template)
                 .append(result2.template);
    });
    

    小提琴:https://jsfiddle.net/szLcfbne/

    【讨论】:

      猜你喜欢
      • 2012-06-22
      • 1970-01-01
      • 2013-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多