
本文介绍了延迟加载到 ui-router 中的多个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
几个月前我创建了主题:
有办法避免这种情况吗?我正在寻找对 templateURL 的延迟加载,但我没有找到.:(
这个 plunkr 是我使用的方法.我的所有视图只有一种状态(我当前的 app.config 有 103 个视图):
routerApp.config(function($stateProvider) {$stateProvider.state('mainState', {意见:{'公司视图':{templateUrl: '公司.html'},'人物视图':{templateUrl: 'People.html'},.........}})});
解决方案
简介
您处理解决方案的方式是您面临问题的原因,因为对于单个状态您有太多视图,最终必须加载所有视图才能设置该状态,所以每次访问状态时,ui-router
都必须加载每个模板以设置视图.对于少数几个模板,这可能不会导致问题,但是,对于像您这样的大量模板,这绝对是一个问题.
Ng 模板
您可以尝试使用 <script type="text/ng-template"...
在您的页面中缓存您的模板,以防止加载时间,这是一个很好的做法道路.通常它是生产构建优化的一部分,加载模板缓存中的所有模板,以便应用程序加载时间显着减少,前提是您不必等待 http 调用来加载页面.它确实会提高您的情况的性能,但我没有一个基准来确保它是否足以满足您的情况.
基于组件的解决方案
无论如何,您始终可以实现界面组件以您想要的方式运行,并以无需加载一百个模板来向用户显示单个面板的方式进行优化.
我的建议是,不要使用ui-router
,而是使用基于组件的解决方案,创建一个指令组件来保存每个窗口的面板内容及其行为;并使用控制器管理打开和关闭面板的状态,在列表中保存和管理每个打开的面板等.例如:
<button ng-click="openPanel({title: '我的面板标题', templateUrl: 'myPanel.html'>">打开我的面板<导航><主要><panel ng-repeat="openPanels 中的面板"></panel></main>
以下代码段使用 bootstrap 4 css 实现了这种方法,每个面板都是一个引导卡,它有一个可以打开的面板列表,点击导航列表时,它将相应的面板添加到打开的面板列表中,其中 angularjs可以使用 ng-repeat
在 html 上呈现它.这样,只会渲染打开的窗口,因此只会加载打开的窗口模板.
免责声明:这是一个非常简单的示例,未使用现有的最佳实践实现.如果您打算使用这种方法,您应该根据您的应用程序来实现它以更好地适应您的架构需求,这不是一个完整的功能组件,它只是一个示例,用于演示.
angular.module('app', []).controller('PanelsCtrl', function($scope) {//要打开的可用窗口$scope.panels = [{ title: 'Window 1', templateUrl: 'window1.html' },{ title: 'Window 2', templateUrl: 'window2.html' }];//所有当前打开的面板$scope.openedPanels = [];//打开一个面板(又名,添加一个面板//到打开的面板列表)$scope.openPanel = 函数(面板){如果 ($scope.openedPanels.indexOf(panel) === -1)$scope.openedPanels.push(panel);};//关闭面板(又名,删除面板//从打开的面板列表中)$scope.onClosePanel = 函数(面板){$scope.openedPanels.splice($scope.openedPanels.indexOf(panel), 1);};}).directive('window', function($templateRequest, $templateCache, $compile) {返回 {限制:'E',范围: {面板:'=',onClosePanel: '&'},模板:`<div class="card"><h4 class="card-header"><span>{{ panel.title }}</span><按钮ng-click="onClosePanel(面板)"类型=按钮"类=关闭"数据关闭=模态"咏叹调标签=关闭"><span aria-hidden="true">×</span><div class="card-body"><ng-include src="panel.templateUrl"></ng-include>
`}})//与 ng-controller 一起使用的示例 controlelr.controller('Window1Ctrl', function($scope) {$scope.window1Prop = '这是来自 Window1Ctrl 的属性'})
@import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css'
<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="面板中的面板"><a class="nav-link active" href="#" ng-click="openPanel(panel)">{{ panel.title }}</a>
<div class="col-sm-9"><window ng-repeat="panel in opensPanels" panel="panel" on-close-panel="onClosePanel(panel)"></窗口>
<!-- NG-模板--><script type="text/ng-template" id="window1.html"><div ng-controller="Window1Ctrl"><b>{{panel.title}}</b><h5>window1Prop: {{ window1Prop }}</p>
<script type="text/ng-template" id="window2.html"><em>{{panel.title}}</em>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
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.
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.
There is a way to avoid this ? I was looking for an lazy load to templateURL but I Didn't find any. :(
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'
},
.....
....
}
})
});
解决方案
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.
Ng-Templates
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.
Component Based Solution
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.
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>
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.
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">×</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 中的多个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
07-22 12:42