Ui-router加载状态,那么我该如何运行一个函数呢?

时间:2022-01-28 12:56:24

I'm new to Angular and states and wrapping my head around ui-router. I've been doing it with jQuery for too long. In jQuery, I can load up something with ajax, then on the success, perhaps run another function. How do you do that with Angular?

我是Angular的新手并指出我的头围绕着ui-router。我用jQuery做了太久了。在jQuery中,我可以用ajax加载一些东西,然后在成功时加载,也许运行另一个函数。你是怎么用Angular做到的?

For example, I have the following

例如,我有以下内容

var ivApp = angular.module('ivApp', ['ui.router']);

ivApp.config(function($urlRouterProvider, $stateProvider){

  $urlRouterProvider.otherwise('/');

  $stateProvider
    .state('home', {
      url: '/',
      templateUrl: 'partials/partial-home.html'
    })

 });

Which simply loads up partial-home.html into my ui-view. But how to tell it to run a function once that is done? For example, I have authenticate.js and a function authenticate(). How do I run authenticate() once 'home' state has loaded?

这只是将partial-home.html加载到我的ui-view中。但是一旦完成,如何告诉它运行一个函数?例如,我有authenticate.js和一个函数authenticate()。一旦'home'状态加载,我如何运行authenticate()?

Additionally, can I tell angular to only load authenticate.js for this state? Or should I have already loaded it in the template. I know that if I include the script in partial-home.html (e.g. <script src="authenticate.js"></script>) chrome throws me an error about synchronous xmlhttprest being deprecated. So somhow in the config, can I declare authenticat.js as a dependency of the state or something like that?

另外,我可以告诉angular只为这个状态加载authenticate.js吗?或者我应该已经将其加载到模板中。我知道如果我将脚本包含在partial-home.html中(例如

At the moment I have worked out I can do something like:

在我锻炼的那一刻,我可以做类似的事情:

ivApp.controller('authenticate', function($scope) {

  // start authorisation
  authenticate();

});

And then define the controller authenticate in my ui-router states. But is that how it's done? It works basically. My authenticate function is doing things like changing things in the DOM, but I read controllers shouldn't be used for this.

然后定义控制器在我的ui-router状态中进行身份验证。但它是如何完成的?它基本上起作用。我的身份验证功能正在做更改DOM中的事情,但我不应该使用控制器。

Thanks for any pointers

谢谢你的任何指示

1 个解决方案

#1


2  

Let's break down into parts.

让我们分解成几部分。

If you just want to load authenticate.js in this particular home state, use ocLazyLoad. It's one of the best way to load a resource lazily. And it works really well if ui-router too!

如果您只想在此特定的home状态下加载authenticate.js,请使用ocLazyLoad。这是懒惰加载资源的最佳方式之一。如果ui-router也很好用!

    $stateProvider.state('index', {
      url: "/", // root route
      views: {
        "lazyLoadView": {
          controller: 'AppCtrl', // This view will use AppCtrl loaded below in the resolve
          templateUrl: 'partial-home.html'
        }
      },
      resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
        loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
          // you can lazy load files for an existing module
                 return $ocLazyLoad.load('js/authenticate.js');
        }]
      }
    });

If you want to run authenticate() once the state is loaded, there are quite a number of ways to do it. One way of course is listening to the $stateChangeSuccess event, but I would avoid using it since you know, global variables, and global variables are bad. I do not want to pollute my $rootScope just because I have a really specific use case.

如果要在加载状态后运行authenticate(),则可以通过多种方式执行此操作。当然,一种方法是监听$ stateChangeSuccess事件,但我会避免使用它,因为你知道,全局变量和全局变量都很糟糕。我不想因为我有一个非常具体的用例而污染我的$ rootScope。

You can use resolve in ui-router too. Resolve is executed after the state is loaded and before the controller is instantiated. I would recommend to use this method as you can chain your promises together with ocLazyLoad, if you are using it (which you should).

您也可以在ui-router中使用resolve。在加载状态之后和实例化控制器之前执行Resolve。我建议使用这种方法,因为你可以将你的承诺与ocLazyLoad一起链接,如果你正在使用它(你应该)。

Manipulating DOMs after a state is loaded? Sure, that's what templateUrl for! Design your template such that it accomadates to your authenticate() functions. If you combine it with resolve, there isn't really much of a problem separating concerns as you would already have executed authenticate() before controller is loaded.

在加载状态后操纵DOM?当然,这就是templateUrl的用途!设计您的模板,使其符合您的authenticate()函数。如果将它与resolve结合使用,那么分离关注点并没有太多问题,因为在加载控制器之前已经执行了authenticate()。

Edit: Adding in Plnkr

编辑:在Plnkr中添加

You want to first lazily-load authenticate.js, and then use the function inside authenticate.js to do something. Since resolve in ui.router executes promise chains in parallel, we have to chain them up, i.e, load your jsfiles first, and then return your status of authentication.

你想首先懒洋洋地加载authenticate.js,然后使用authenticate.js中的函数来做某事。由于ui.router中的resolve会并行执行promise链,我们必须将它们链接起来,即首先加载jsfiles,然后返回你的身份验证状态。

We need to declare a deferred promise using $q service. We then return this promise in the resolve, so that you controller is listening to one promise instead of two. Here is how:

我们需要使用$ q服务声明延期保证。然后我们在决心中返回此承诺,以便您的控制器正在听一个承诺而不是两个。方法如下:

 $stateProvider
  .state('Home', {
    templateUrl: 'home.html',
    controller: 'homeCtrl',
    resolve: {
      //need to chain our promises since we neeed to first load the authenticate.js
      //and second, execute authenticate()
      loadJsAndAuth: ['$ocLazyLoad', '$q', '$injector', function($ocLazyLoad, $q, $injector) {
        //declare a deferred promise
        var deferred = $q.defer();

        //now load the authenticate.js
        $ocLazyLoad.load('authenticate.js').then(
          //load successful! proceed to use our authenticate function!
          function(success) {
            //since we already have loaded authenticatejs, now we can inject the service and use it
            var authSvc = $injector.get('authenticateSvc');

            //this is just a demo on how to authenticate. 
            //change this to banana to see the authenticate fail
            var fruits = 'apple'

            if (authSvc.authenticate(fruits)) {
              //authenticate pass, resolve the promise!
              deferred.resolve('authenticated!');
            }
            //authenticate fail, reject the promise
            deferred.reject('authenticate failed');

          },
          //load of jsfiles failed! reject the promise.
          function(error) {
            deferred.reject('Cannot load authenticate.js')
          })

        return deferred.promise;
      }]
    }
  })

And in your controller, you can get the resolved promises!

在您的控制器中,您可以获得已解决的承诺!

//you can get access to what is is being resolved by loadJsAndAuth
.controller('homeCtrl', ['$scope', 'loadJsAndAuth', function($scope, loadJsAndAuth) {

  $scope.status = loadJsAndAuth // this is resolved promises.

}]);

#1


2  

Let's break down into parts.

让我们分解成几部分。

If you just want to load authenticate.js in this particular home state, use ocLazyLoad. It's one of the best way to load a resource lazily. And it works really well if ui-router too!

如果您只想在此特定的home状态下加载authenticate.js,请使用ocLazyLoad。这是懒惰加载资源的最佳方式之一。如果ui-router也很好用!

    $stateProvider.state('index', {
      url: "/", // root route
      views: {
        "lazyLoadView": {
          controller: 'AppCtrl', // This view will use AppCtrl loaded below in the resolve
          templateUrl: 'partial-home.html'
        }
      },
      resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
        loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
          // you can lazy load files for an existing module
                 return $ocLazyLoad.load('js/authenticate.js');
        }]
      }
    });

If you want to run authenticate() once the state is loaded, there are quite a number of ways to do it. One way of course is listening to the $stateChangeSuccess event, but I would avoid using it since you know, global variables, and global variables are bad. I do not want to pollute my $rootScope just because I have a really specific use case.

如果要在加载状态后运行authenticate(),则可以通过多种方式执行此操作。当然,一种方法是监听$ stateChangeSuccess事件,但我会避免使用它,因为你知道,全局变量和全局变量都很糟糕。我不想因为我有一个非常具体的用例而污染我的$ rootScope。

You can use resolve in ui-router too. Resolve is executed after the state is loaded and before the controller is instantiated. I would recommend to use this method as you can chain your promises together with ocLazyLoad, if you are using it (which you should).

您也可以在ui-router中使用resolve。在加载状态之后和实例化控制器之前执行Resolve。我建议使用这种方法,因为你可以将你的承诺与ocLazyLoad一起链接,如果你正在使用它(你应该)。

Manipulating DOMs after a state is loaded? Sure, that's what templateUrl for! Design your template such that it accomadates to your authenticate() functions. If you combine it with resolve, there isn't really much of a problem separating concerns as you would already have executed authenticate() before controller is loaded.

在加载状态后操纵DOM?当然,这就是templateUrl的用途!设计您的模板,使其符合您的authenticate()函数。如果将它与resolve结合使用,那么分离关注点并没有太多问题,因为在加载控制器之前已经执行了authenticate()。

Edit: Adding in Plnkr

编辑:在Plnkr中添加

You want to first lazily-load authenticate.js, and then use the function inside authenticate.js to do something. Since resolve in ui.router executes promise chains in parallel, we have to chain them up, i.e, load your jsfiles first, and then return your status of authentication.

你想首先懒洋洋地加载authenticate.js,然后使用authenticate.js中的函数来做某事。由于ui.router中的resolve会并行执行promise链,我们必须将它们链接起来,即首先加载jsfiles,然后返回你的身份验证状态。

We need to declare a deferred promise using $q service. We then return this promise in the resolve, so that you controller is listening to one promise instead of two. Here is how:

我们需要使用$ q服务声明延期保证。然后我们在决心中返回此承诺,以便您的控制器正在听一个承诺而不是两个。方法如下:

 $stateProvider
  .state('Home', {
    templateUrl: 'home.html',
    controller: 'homeCtrl',
    resolve: {
      //need to chain our promises since we neeed to first load the authenticate.js
      //and second, execute authenticate()
      loadJsAndAuth: ['$ocLazyLoad', '$q', '$injector', function($ocLazyLoad, $q, $injector) {
        //declare a deferred promise
        var deferred = $q.defer();

        //now load the authenticate.js
        $ocLazyLoad.load('authenticate.js').then(
          //load successful! proceed to use our authenticate function!
          function(success) {
            //since we already have loaded authenticatejs, now we can inject the service and use it
            var authSvc = $injector.get('authenticateSvc');

            //this is just a demo on how to authenticate. 
            //change this to banana to see the authenticate fail
            var fruits = 'apple'

            if (authSvc.authenticate(fruits)) {
              //authenticate pass, resolve the promise!
              deferred.resolve('authenticated!');
            }
            //authenticate fail, reject the promise
            deferred.reject('authenticate failed');

          },
          //load of jsfiles failed! reject the promise.
          function(error) {
            deferred.reject('Cannot load authenticate.js')
          })

        return deferred.promise;
      }]
    }
  })

And in your controller, you can get the resolved promises!

在您的控制器中,您可以获得已解决的承诺!

//you can get access to what is is being resolved by loadJsAndAuth
.controller('homeCtrl', ['$scope', 'loadJsAndAuth', function($scope, loadJsAndAuth) {

  $scope.status = loadJsAndAuth // this is resolved promises.

}]);