从服务器加载 html 和 Controller 并创建动态状态 UI - 路由器 [英] Loading html and Controller from server and creating dynamic states UI - router

查看:14
本文介绍了从服务器加载 html 和 Controller 并创建动态状态 UI - 路由器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking for a Solution to load my App Content dynamically from the Server.

我的场景:

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

Lets say we have 2 Users (A and B), my App consists of different Modules like lets say a shoppingList and a calculator, now my goal would be the User logs into my App from the Database I get the User rights and depending what rights he has, i would load the html for the views and the controller files for the logic part from the Server, while doing that I would create the states needed for the html and ctrl. So basically my App is very small consistent of the Login and everything else is getting pulled from the Server depending on the Userrights.

我使用的:

  1. 科尔多瓦
  2. AngularJs
  3. 离子框架

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

Why I need it to be all dynamic:

1) 可能有一个只包含登录逻辑的应用程序,因此在修复错误或添加模块时,我只需将文件添加到服务器,为用户提供权限,无需更新即可应用程序.

1)The possiblity to have an App that contains just the login logic, so when fixing bugs or adding Modules I only have to add the files to the server give the User the right for it and it is there without needing to update the app.

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

2)The User only has the functionality he needs, he doesnt need to have everything when he only has the right for 1 module.

3) 目前应用程序变得非常大,这意味着每个模块都有大约 5-10 个状态,有自己的 html 和控制器.目前计划了 50 个不同的模块,因此您可以进行数学计算.

3)The App grows very big at the moment, meaning every Module has like 5-10 states, with their own html and Controllers. currently there are 50 different Modules planned so you can do the math.

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

I looked at this to get some inspiration:

AngularJS、ocLazyLoad &加载动态状态

到目前为止我尝试过的:

What I tried so far:

我创建了 1 个包含整个模块的 Html 文件,所以我只有 1 个 http 请求:

I created 1 Html file which contains the whole module so I only have 1 http request:

假设这是我在用户登录后服务器的响应

Lets say this is my response from the server after the User logged in

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

          }
        }
     });

控制器部分:

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

          }
        }
     });

加载控制器后,我尝试注册它们:

After loading the Controllers I try to register them:

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

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

Which is not working since this is only a string...

定义提供者:

.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-路由器部分:

//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 文件并将它们存储在 templateCache 中,甚至加载它们,但前提是状态是预定义的.查看该项目再次出现可能这与缓存有关我不太确定...

I have managed to load the html files and store them in the templateCache, even load them but only if the states were predefined.What I noticed here was that sometimes lets say when I remove an item from a List and come back to the View the item was there again maybe this has something to do with cache I am not really sure...

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

I have managed to load the controller files and save the controllers in the templateCache but I dont really know how to use the $ControllerPrioviderRef.register with my stored strings...

创建状态确实有效但控制器不适合所以我无法打开任何视图...

Creating the states did work but the Controller didnt fit so i could not open any views...

PS:我还查看了 require.js 和 OCLazyLoad 以及这个示例 动态控制器示例

PS: I also looked at require.js and OCLazyLoad as well as this example dynamic controller example

更新:

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

Okay so I managed to load the Html , create the State with the Controller everything seems to work fine, except that the Controller does not seem to work at all, there are no errors, but it seems nothing of the Controller logic is executed. Currently the only solution to register the controller from the previous downloaded file was to use eval(), which is more a hack then a proper solution.

代码如下:

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

        }
    }
}])

感谢任何帮助

推荐答案

好的,让我们从头开始吧.

Ok, so let's start from the beginning.

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

All the application logic should be contained on the server and served via API-calls through REST, SOAP or similar. By doing so, you reduce the amount of logic built into the UI, which reduces the stress on the client. This basically makes your client app a rendering agent, containing only models and views for the data and logic served by the backend API.

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

As foreyez stated in his/her comment, this isn't an issue for any modern (or half-modern) device.

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

If you insist on not loading all of the layouts at once, you could of course separate them into partials, which you load after the login based on the user privileges. By doing so, you reduce the amount of in-memory data, even though the improvement would be doubtable, at best.

这篇关于从服务器加载 html 和 Controller 并创建动态状态 UI - 路由器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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