延迟加载到ui-router中的多个视图 [英] Lazyload to multiple views in ui-router

查看:84
本文介绍了延迟加载到ui-router中的多个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几个月前,我已经创建了一个主题:

A few months ago I've be created the topic: Try to render two templates in same View (Ui-Router), where I asked about how to render multiple views in the same page. My objective with this was created a web app as an desktop one, with views to minimize, maximize, close and stuff like that.

好吧,我的应用程序已经准备好了,但是我遇到了一个问题,当我将应用程序上线到生产环境时,某些计算机需要很长时间才能呈现所有视图.在下面的图片中,我们可以看到服务器要返回我的templateURL的大量申请.

Well, my app is ready but I'm getting a problem, when I up my app to the production some computers are taking a long time to render all the Views. In the image bellow we can se a lot of requisitions that server take to return my templatesURL's.

有办法避免这种情况吗?我一直在寻找对templateURL的延迟加载,但未找到任何内容. :(

There is a way to avoid this ? I was looking for an lazy load to templateURL but I Didn't find any. :(

这是我使用的方法.我所有的视图都只有一个状态(我当前的app.config有103个视图):

This plunkr was the approach what I used. I have only one state for all my Views (My current app.config has 103 Views):

routerApp.config(function($stateProvider) {

  $stateProvider.state('mainState', {
    views: {
      'CompanyView': {
        templateUrl: 'Company.html'
      },
      'PeopleView': {
        templateUrl: 'People.html'
      },
     .....
     ....
    }
  })


});

推荐答案

简介

解决方案的方式是所面临问题的原因,因为对于单个状态您有太多的视图,因此最终必须加载所有视图才能设置该状态,因此每次访问状态时,ui-router必须加载每个模板才能设置视图.对于一些模板来说,这可能不会引起问题,但是对于像您这样的更大数量的模板,这绝对是一个问题.

Introduction

The way you approached the solution is the cause of the problem you're facing, because you have too many views for a single state, it'll end up having to load all of them in order to set that state, so every time you access your state, ui-router has to load every template in order to set the views. It might not cause problem for a few number of templates, but, for larger numbers like yours it is definitely an issue.

您可以尝试使用<script type="text/ng-template"...将模板缓存在页面中,以防止加载时间,顺便说一句,这是一个好习惯.通常,这是生产构建优化的一部分,将所有模板加载到模板缓存中,从而使应用程序加载时间大大减少,前提是您不必等待http调用即可加载页面.确实可以提高您的性能,但是我没有基准来确保它是否足以满足您的情况.

You can try to cache your templates in your page using <script type="text/ng-template"... in order to prevent the loading time, it's a good practice by the way. Usually it's part of the production build optimization, load all templates in the template cache, so that the application load time decreases significantly provided that you don't have to wait for an http call to load a page. It will indeed increase the performance in your case, but I don't have a benchmark that ensure if it'd be enough for your scenario.

无论如何,您始终可以实现界面组件以所需的方式运行,并以不必加载一百个模板即可为用户显示单个面板的方式进行优化.

Anyhow, you can always implement interface components to behave the way you want, optimized in such a way that it doesn't have to load one hundred templates to show a single panel for the user.

我的建议是,不要使用ui-router,而是使用基于组件的解决方案,创建一个指令组件来保存每个窗口的面板内容及其行为;并使用控制器来管理已打开和已关闭面板的状态,保持和管理列表中的每个已打开面板等.例如:

My suggestion is, instead of using ui-router, use a component based solution, create a directive component to hold the panel content of each window and its behavior; and use a controller to manage the state of opened and closed panels, holding and managing each opened panel in a list and so on. For example:

<nav>
  <button ng-click="openPanel({title: 'My Panel Title', templateUrl: 'myPanel.html'>">
    Open myPanel
  </button>
<nav>
<main>
  <panel ng-repeat="panel in openedPanels"></panel>
</main>

以下代码段使用bootstrap 4 css实现此方法,每个面板是一个bootstrap卡,并且具有可以打开的面板列表,单击导航列表时,它将相应的面板添加到打开的面板列表中,其中angularjs可以使用ng-repeat将其呈现在html上.这样,将仅渲染打开的窗口,因此,将仅加载打开的窗口模板.

The following snippet implements this approach using bootstrap 4 css, each panel is a bootstrap card, and it has a list of panels it can open and on click of a nav list it adds the respective panel to the opened panels list where angularjs can render it on the html using ng-repeat. This way, only the opened window will be rendered, therefore, only the opened window template will be loaded.

免责声明:这是一个非常简单的示例,没有使用现有的最佳实践来实现.如果您打算使用这种方法,则应根据您的应用程序来实现它,以更好地满足体系结构的需求,但这不是一个完整的功能组件,仅为了示例而已.

Disclaimer: This is a very simple example implemented not using the best practices available out there. If you intend to use this approach you should implement it based on your application to fit better the needs of your architecture, this one is not a complete functional component, it's just an example for the sake of the demonstration.

angular.module('app', [])
  .controller('PanelsCtrl', function($scope) {
  
    // available windows to be opened
    $scope.panels = [
      { title: 'Window 1', templateUrl: 'window1.html' },
      { title: 'Window 2', templateUrl: 'window2.html' }];
    
    // all currently opened panels
    $scope.openedPanels = [];
    
    // opens a panel (a.k.a, adds a panel
    //  to the opened panels list)
    $scope.openPanel = function(panel) {
      if ($scope.openedPanels.indexOf(panel) === -1)
        $scope.openedPanels.push(panel);
    };
    
    // close a panel (a.k.a, removes a panel
    //  from the opened panels list)
    $scope.onClosePanel = function(panel) {
      $scope.openedPanels.splice($scope.openedPanels.indexOf(panel), 1);
    };
  })
  .directive('window', function($templateRequest, $templateCache, $compile) {
    return {
      restrict: 'E',
      scope: {
        panel: '=',
        onClosePanel: '&'
      },
      template: `
        <div class="card">
          <h4 class="card-header">
            <span>{{ panel.title }}</span>
            <button
              ng-click="onClosePanel(panel)"
              type="button"
              class="close"
              data-dismiss="modal"
              aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </h4>
          <div class="card-body">
          	<ng-include src="panel.templateUrl"></ng-include>
          </div>
        </div>
      `
    }
  })
  // example controlelr to be used with ng-controller
  .controller('Window1Ctrl', function($scope) {
    $scope.window1Prop = 'This is a property from Window1Ctrl'
  })

@import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css'

<div ng-app="app">
  <div class="container" ng-controller="PanelsCtrl">
    <div class="row">
      <div class="col-sm-3">
        <ul class="nav flex-column">
          <li class="nav-item" ng-repeat="panel in panels">
            <a class="nav-link active" href="#" ng-click="openPanel(panel)">
            {{ panel.title }}
          </a>
          </li>
        </ul>
      </div>
      <div class="col-sm-9">
        <window ng-repeat="panel in openedPanels" panel="panel" on-close-panel="onClosePanel(panel)">
        </window>
      </div>
    </div>
  </div>
  
  <!-- NG-TEMPLATES -->
  
  <script type="text/ng-template" id="window1.html">
    <div ng-controller="Window1Ctrl">
      <b>{{panel.title}}</b>
      <h5>window1Prop: {{ window1Prop }}</p>
    </div>
  </script>
  <script type="text/ng-template" id="window2.html">
    <em>{{panel.title}}</em>
  </script>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>

这篇关于延迟加载到ui-router中的多个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆