Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.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
Backbone.js 主干路由器或视图是否应处理获取数据和显示加载状态?_Backbone.js - Fatal编程技术网

Backbone.js 主干路由器或视图是否应处理获取数据和显示加载状态?

Backbone.js 主干路由器或视图是否应处理获取数据和显示加载状态?,backbone.js,Backbone.js,在我的应用程序的许多地方,都会发生以下情况: 用户点击一些链接触发导航 需要提取数据以呈现视图 UI设计要求在获取数据时显示“加载”微调器 获取数据后,我们将显示渲染视图 我尝试了以下两种实现模式: 路由器处理抓取 路由器告诉容器视图显示加载微调器 路由器加载任何集合/模型 路由器告诉容器视图隐藏加载微调器 路由器将集合/模型传递给视图并渲染它 视图句柄获取 路由器只是创建和渲染视图 视图获取所需的集合和模型 第一次渲染视图时,它仅显示加载微调器,因为数据仍在加载 当数据到达时,模型/

在我的应用程序的许多地方,都会发生以下情况:

  • 用户点击一些链接触发导航
  • 需要提取数据以呈现视图
  • UI设计要求在获取数据时显示“加载”微调器
  • 获取数据后,我们将显示渲染视图
我尝试了以下两种实现模式:

  • 路由器处理抓取

    • 路由器告诉容器视图显示加载微调器
    • 路由器加载任何集合/模型
    • 路由器告诉容器视图隐藏加载微调器
    • 路由器将集合/模型传递给视图并渲染它
  • 视图句柄获取

    • 路由器只是创建和渲染视图
    • 视图获取所需的集合和模型
    • 第一次渲染视图时,它仅显示加载微调器,因为数据仍在加载
    • 当数据到达时,模型/集合将触发事件,视图将绑定到这些事件,以便重新呈现自身,从而隐藏加载微调器并显示完整视图
  • 我不喜欢#1,因为路由器变成了一个巨大的模型/集合获取逻辑球,似乎有太多的责任#2似乎是一个更好的职责分配(路由器只是决定显示哪个视图,视图确定需要获取什么数据),但它确实使视图呈现变得有点棘手,因为它现在是有状态的


    StackOverflow社区是怎么想的?1、2或其他什么?

    我倾向于将第二个选项与三个视图一起使用,即容器、加载视图和内容视图。也就是说,容器由路由器实例化,在每次渲染期间,它查看手头上要显示的内容(有时由路由器提供,有时由自身提供),并决定实例化哪个视图。一个过于简单、人为的例子:

    ContainerView = Backbone.View.extend({
    
      initialize: function (options) {
        options.data.bind("reset", this.render, this);
      },
    
      render: function () {
        var view;
    
        // If the loading view is only shown once, e.g., splashing, then isReady()
        // may be better here.
        if (this.options.data.isLoading()) {
          view = LoadingView;
        } else {
          view = DataView;
        }
    
        this.$("div.content").html(new view().render().el);
      }
    
    });
    
    我喜欢这种方法,因为:

    • 路由器只知道将用户发送到哪里
    • 外部视图只知道用户应该查看什么(给定其数据)
    • 内部视图只知道如何显示它们的一小部分(并且可以在其他地方使用);及
    • 渲染函数始终显示当前正确的内容
    澄清:
    在这种情况下,视图的目的是理解如何最好地向用户显示要显示的内容。在这种情况下,仍在加载的数据最好用加载视图显示,而就绪数据最好用数据视图显示。大多数真实视图实际上都包含了更多视图,例如,根据用户授权不同的操作容器。

    这篇文章很老了,但我们今天早些时候已经对它进行了回顾,所以如果其他人看到它:

    对我来说,我确实看到了两个不同的问题:

  • 在路由器或视图中,数据获取机制和结果视图呈现应该发生在哪里
  • 视图应该期望已解析的模型,还是应该响应可能仍在加载的模型
  • 我们的一些处理方法与一些个人偏好混合在一起:

  • 都不是,尽管我会靠得更近。路由器应该处理路由,视图应该处理查看,其他东西应该处理模型/集合获取逻辑的机制和工作流。我们称之为控制器,路由器基本上委托给它
  • 正如尤里所暗示的,“有时”是一个现实。我认为这可能是一个个案决定,但最终应该是控制器和视图之间的契约,而不是路由器/视图之间的契约 我喜欢尤里的要点,还有几个警告(缩进的子弹):

    • 路由器只知道将用户发送到哪里
    • 外部视图只知道用户应该查看什么(给定其数据)
      • 假设外部视图特定于内部视图的用例,并且由另一个视图“拥有”(用于清理)
      • 另外,对于一般容器(如渲染到“主”位置),我们发现使用一个组件来管理页面上某个“部分”的视图非常有用—我们称之为渲染器
    • 内部视图只知道如何显示它们的一小部分(以及 可在其他地方使用)
    • 并且渲染函数始终显示当前正确的内容。
      • 对于通用容器,最终将由渲染器负责
    渲染器的主要原因是处理与该部分相关的事情,例如清理现有视图以避免重影视图,在渲染时滚动到顶部(我们的MainContentRenderer会这样做),或者在这种情况下显示微调器

    一个psuedo代码示例,它可能看起来像什么,例如:

    • 通用内容目标“main”(如果它是特定于用例的,根据Yuri的示例,最好使用ComponentView,这取决于您的视图生命周期管理策略)
    • 我们必须去拿一个模型并等待它
    • 接受已加载模型的视图
    路由器:

    routes: {
        "profile": "showProfile"
    },
    
    showProfile: function() {
        return new ProfileController().showProfile();
    }
    
    showProfile: function() {
        //simple case
        var model = new Model();
        var deferredView = model.fetch.then(function() {
            return new View(model);
        };
        MainContentRenderer.renderDeferred(deferredView);
    }
    
    var currentView;
    
    renderDeferred: function(deferredView) {
        showSpinner();
        deferredView.then(function(view) {
            this.closeSpinner();
            this.closeCurrentView();
            this.render(view);
        }
    },
    
    render: function(view) {
        currentView = view;
        $('#main-content').html(view.render().el);
    }
    
    closeCurrentView: function() {
        if (currentView and currentView.close()) {
            currentView.close();
        }
    }
    
    配置文件控制器:

    routes: {
        "profile": "showProfile"
    },
    
    showProfile: function() {
        return new ProfileController().showProfile();
    }
    
    showProfile: function() {
        //simple case
        var model = new Model();
        var deferredView = model.fetch.then(function() {
            return new View(model);
        };
        MainContentRenderer.renderDeferred(deferredView);
    }
    
    var currentView;
    
    renderDeferred: function(deferredView) {
        showSpinner();
        deferredView.then(function(view) {
            this.closeSpinner();
            this.closeCurrentView();
            this.render(view);
        }
    },
    
    render: function(view) {
        currentView = view;
        $('#main-content').html(view.render().el);
    }
    
    closeCurrentView: function() {
        if (currentView and currentView.close()) {
            currentView.close();
        }
    }
    
    MainContentRenderer:

    routes: {
        "profile": "showProfile"
    },
    
    showProfile: function() {
        return new ProfileController().showProfile();
    }
    
    showProfile: function() {
        //simple case
        var model = new Model();
        var deferredView = model.fetch.then(function() {
            return new View(model);
        };
        MainContentRenderer.renderDeferred(deferredView);
    }
    
    var currentView;
    
    renderDeferred: function(deferredView) {
        showSpinner();
        deferredView.then(function(view) {
            this.closeSpinner();
            this.closeCurrentView();
            this.render(view);
        }
    },
    
    render: function(view) {
        currentView = view;
        $('#main-content').html(view.render().el);
    }
    
    closeCurrentView: function() {
        if (currentView and currentView.close()) {
            currentView.close();
        }
    }
    

    引入控制器还具有可测试性的额外好处。例如,我们有复杂的规则来围绕URL管理执行搜索,在结果视图和新搜索视图之间进行选择,在缓存的“最后一次”搜索结果和执行新搜索之间进行选择。我们对控制器进行了Jasmine测试,以验证所有流逻辑是否正确。它还提供了一个独立的位置来管理这些规则。

    您编写的
    isLoading
    isReady
    函数也是这样吗?假设您将
    选项.data
    向下传递到数据视图