sta*_*g91 16 javascript requirejs angularjs angular-ui-router oclazyload
我正在寻找一个从服务器动态加载我的应用程序内容的解决方案.
我的场景:
让我们说我们有2个用户(A和B),我的应用程序包含不同的模块,比如说一个shoppingList和一个计算器,现在我的目标是用户从数据库登录我的应用程序我获得用户权限并取决于什么权利他有,我会从服务器加载视图的html和逻辑部分的控制器文件,同时这样做我将创建html和ctrl所需的状态.因此,基本上我的应用程序与Login的一致性非常小,其他所有内容都取决于Userrights从服务器中提取.
我用的是什么:
为什么我需要它全部动态:
1)拥有一个仅包含登录逻辑的应用程序的可能性,因此在修复错误或添加模块时,我只需要将文件添加到服务器,即可为用户提供权利,而无需更新应用程序.
2)用户只有他需要的功能,当他只有1个模块的权利时,他不需要拥有一切.
3)应用程序的增长在此刻非常大的,这意味着每个模块有一个像5-10状态,用自己的HTML和控制器.目前有50个不同的模块计划,所以你可以做数学.
我看了这个以获得一些灵感:
到目前为止我尝试了什么:
我创建了1个包含整个模块的Html文件,因此我只有1个http请求:
让我们说这是用户登录后来自服务器的响应
HTML部分:
var rights= [A,B,C,D]
angular.forEach(rights, function (value, key) {
$http.get('http://myServer.com/templates/' + value + '.html').then(function (response) {
//HTML file for the whole module
splits = response.data.split('#');
//Array off HTMl strings
for (var l = 1; l <= splits.length; l++) {
//Putting all Html strings into templateCache
$templateCache.put('templates/' + value +'.html', splits[l - 1]);
}
}
});
Run Code Online (Sandbox Code Playgroud)
控制器部分:
var rights= [A,B,C,D]
angular.forEach(rights, function (value, key) {
$http.get('http://myServer.com/controller/' + value + '.js').then(function (response) {
// 1 file for the whole module with all controllers
splits = response.data.split('#');
//Array off controller strings
for (var l = 1; l <= splits.length; l++) {
//Putting all Controller strings into templateCache
$templateCache.put('controllers/' + value +'.js', splits[l - 1]);
}
}
});
Run Code Online (Sandbox Code Playgroud)
加载控制器后,我尝试注册它们:
$controllerProvider.register('SomeName', $templateCache.get('controllers/someController));
Run Code Online (Sandbox Code Playgroud)
哪个不起作用,因为这只是一个字符串......
定义提供者:
.config(function ($stateProvider, $urlRouterProvider, $ionicConfigProvider, $controllerProvider) {
// turns of the page transition globally
$ionicConfigProvider.views.transition('none');
$stateProviderRef = $stateProvider;
$urlRouterProviderRef = $urlRouterProvider;
$controllerProviderRef = $controllerProvider;
$stateProvider
//the login state is static for every user
.state('login', {
url: "/login",
templateUrl: "templates/login.html",
controller: "LoginCtrl"
});
//all the other states are missing and should be created depending on rights
$urlRouterProvider.otherwise('/login');
});
Run Code Online (Sandbox Code Playgroud)
Ui-Router部分:
//Lets assume here the Rights Array contains more information like name, url...
angular.forEach(rights, function (value, key) {
//Checks if the state was already added
var getExistingState = $state.get(value.name)
if (getExistingState !== null) {
return;
}
var state = {
'lang': value.lang,
'params': value.param,
'url': value.url,
'templateProvider': function ($timeout, $templateCache, Ls) {
return $timeout(function () {
return $templateCache.get("templates" + value.url + ".html")
}, 100);
},
'ControllerProvider': function ($timeout, $templateCache, Ls) {
return $timeout(function () {
return $templateCache.get("controllers" + value.url + ".js")
}, 100);
}
$stateProviderRef.state(value.name, state);
});
$urlRouter.sync();
$urlRouter.listen();
Run Code Online (Sandbox Code Playgroud)
目前的情况:
我已经设法加载html文件并将它们存储在templateCache中,甚至加载它们但是只有在状态是预定义的时候才会加载它们.我注意到这里有时会说当我从List中删除一个项目然后回到View项目又在那里也许这与缓存有关我不太确定...
我已经设法加载控制器文件并将控制器保存在templateCache中,但我真的不知道如何使用$ ControllerPrioviderRef.register与我存储的字符串...
创建状态确实有效但控制器不合适所以我无法打开任何视图......
PS:我还查看了require.js和OCLazyLoad以及此示例动态控制器示例
更新:
好的,所以我设法加载Html,创建State与Controller一切似乎工作正常,除了控制器似乎根本没有工作,没有错误,但似乎没有任何控制器逻辑执行.目前,从先前下载的文件中注册控制器的唯一解决方案是使用eval(),哪个更糟糕,然后是正确的解决方案.
这里的代码:
.factory('ModularService', ['$http', ....., function ( $http, ...., ) {
return {
LoadModularContent: function () {
//var $state = $rootScope.$state;
var json = [
{
module: 'Calc',
name: 'ca10',
lang: [],
params: 9,
url: '/ca10',
templateUrl: "templates/ca/ca10.html",
controller: ["Ca10"]
},
{
module: 'SL',
name: 'sl10',
lang: [],
params: 9,
url: '/sl10',
templateUrl: "templates/sl/sl10.html",
controller: ['Sl10', 'Sl20', 'Sl25', 'Sl30', 'Sl40', 'Sl50', 'Sl60', 'Sl70']
}
];
//Load the html
angular.forEach(json, function (value, key) {
$http.get('http://myserver.com/' + value.module + '.html')
.then(function (response) {
var splits = response.data.split('#');
for (var l = 1; l <= value.controller.length; l++) {
$templateCache.put('templates/' + value.controller[l - 1] + '.html', splits[l - 1]);
if (l == value.controller.length) {
$http.get('http://myserver.com//'+value.module+'.js')
.then(function (response2) {
var ctrls = response2.data.split('##');
var fullctrl;
for (var m = 1; m <= value.controller.length; m++){
var ctrlName = value.controller[m - 1] + 'Ctrl';
$controllerProviderRef
.register(ctrlName, ['$scope',...., function ($scope, ...,) {
eval(ctrls[m - 1]);
}])
if (m == value.controller.length) {
for (var o = 1; o <= value.controller.length; o++) {
var html = $templateCache
.get("templates/" + value.controller[o - 1] + ".html");
var getExistingState = $state.get(value.controller[o - 1].toLowerCase());
if (getExistingState !== null) {
return;
}
var state = {
'lang': value.lang,
'params': value.param,
'url': '/' + value.controller[o - 1].toLowerCase(),
'template': html,
'controller': value.controller[o - 1] + 'Ctrl'
};
$stateProviderRef.state(value.controller[o - 1].toLowerCase(), state);
}
}
}
});
}
}
});
});
// Configures $urlRouter's listener *after* your custom listener
$urlRouter.sync();
$urlRouter.listen();
}
}
}])
Run Code Online (Sandbox Code Playgroud)
任何帮助赞赏
好吧,让我们从头开始吧。
所有应用程序逻辑都应包含在服务器上,并通过 REST、SOAP 或类似方式通过 API 调用提供服务。通过这样做,您可以减少 UI 中内置的逻辑量,从而减轻客户端的压力。这基本上使您的客户端应用程序成为渲染代理,仅包含后端 API 提供的数据和逻辑的模型和视图。
正如 foreyez 在他/她的评论中所说,这对于任何现代(或半现代)设备来说都不是问题。
如果您坚持不一次加载所有布局,您当然可以将它们分成部分布局,在登录后根据用户权限加载。通过这样做,您可以减少内存中的数据量,尽管这种改进充其量是值得怀疑的。