javascript - 从服务器加载 html 和 Controller 并创建动态状态 UI - 路由器

标签 javascript angularjs requirejs angular-ui-router oclazyload

我正在寻找一种从服务器动态加载我的应用程序内容的解决方案。

我的场景:

假设我们有 2 个用户(A 和 B),我的应用程序由不同的模块组成,比如一个购物列表和一个计算器,现在我的目标是用户从数据库登录我的应用程序我获得用户权限和根据他拥有的权利,我将从服务器加载 View 的 html 和逻辑部分的 Controller 文件,同时我将创建 html 和 ctrl 所需的状态。所以基本上我的应用程序非常小,与登录一致,其他所有内容都根据用户权限从服务器中提取。

我用的是什么:

  1. Cordova
  2. AngularJs
  3. ionic 框架

为什么我需要它是动态的:

1) 拥有一个仅包含登录逻辑的应用程序的可能性,因此在修复错误或添加模块时,我只需将文件添加到服务器,为用户提供它的权利,它就在那里而无需更新应用程序。

2)用户只有他需要的功能,当他只有一个模块的权利时,他不需要拥有一切。

3) 应用程序现在变得非常大,这意味着每个模块都有大约 5-10 个状态,有自己的 html 和 Controller 。目前计划有 50 个不同的模块,您可以算一下。

我看了这个是为了获得一些灵感:

AngularJS, ocLazyLoad & loading dynamic States

到目前为止我尝试了什么:

我创建了 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]);

          }
        }
     });

Controller 部分:

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]);

          }
        }
     });

加载 Controller 后,我尝试注册它们:

$controllerProvider.register('SomeName', $templateCache.get('controllers/someController));

这是行不通的,因为这只是一个字符串...

定义提供者:

.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');


});

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();

目前情况:

我已经设法加载 html 文件并将它们存储在模板缓存中,甚至加载它们,但前提是状态是预定义的。我在这里注意到的是,有时可以说当我从列表中删除一个项目并返回时再次查看该项目可能与缓存有关我不太确定...

我已经设法加载 Controller 文件并将 Controller 保存在 templateCache 中,但我真的不知道如何将 $ControllerPrioviderRef.register 与我存储的字符串一起使用...

创建状态确实有效,但 Controller 不适合所以我无法打开任何 View ...

PS:我还查看了 require.js 和 OCLazyLoad 以及这个示例 dynamic controller example

更新:

好的,所以我设法加载了 Html ,使用 Controller 创建了 State 一切似乎都工作正常,除了 Controller 确实似乎根本不起作用,没有错误,但似乎没有执行任何 Controller 逻辑。目前,从先前下载的文件注册 Controller 的唯一解决方案是使用 eval(),,这更像是一种 hack,而不是一个合适的解决方案。

这里是代码:

.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();

        }
    }
}])

感谢任何帮助

最佳答案

好的,让我们从头开始。

所有应用程序逻辑都应包含在服务器上,并通过 REST、SOAP 或类似工具通过 API 调用提供服务。通过这样做,您可以减少 UI 中内置的逻辑量,从而减轻客户端的压力。这基本上使您的客户端应用程序成为渲染代理,仅包含后端 API 提供的数据和逻辑的模型和 View 。

正如 foreyez 在他/她的评论中所说,这对任何现代(或半现代)设备来说都不是问题。

如果您坚持不一次加载所有布局,您当然可以将它们分成部分,根据用户权限在登录后加载。通过这样做,您可以减少内存中的数据量,即使这种改进充其量是值得怀疑的。

关于javascript - 从服务器加载 html 和 Controller 并创建动态状态 UI - 路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35042277/

相关文章:

javascript - 响应式 CSS/Bootstrap : Show modal Dialog for small screen, 否则显示 block 元素

php - 将变量传递给外部 PHP 文件

javascript - 所有状态的 Angular ui 路由器多个命名 View

Navbar 问题的 HTML 重组

javascript - 关于 RequireJS 和依赖项的一些让我烦恼的事情

javascript - 数据主脚本加载和普通脚本加载之间的区别

javascript - 使用存储在变量中的 jQuery 句柄

javascript - 如何创建 "endless"滚动幻灯片?

javascript - Angular ng-禁用检查多个值

javascript - 使用 TypeScript 定义 Durandal ViewModel