简体   繁体   English

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

[英]Ui-router loads state, then how can I run a function?

I'm new to Angular and states and wrapping my head around ui-router. 我是Angular的新手,并指出我的头围绕着ui-router。 I've been doing it with jQuery for too long. 我用jQuery做了太久了。 In jQuery, I can load up something with ajax, then on the success, perhaps run another function. 在jQuery中,我可以用ajax加载一些东西,然后在成功时加载,也许运行另一个函数。 How do you do that with Angular? 你是怎么用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 . 这只是将partial-home.html加载到我的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() . 例如,我有authenticate.js和一个函数authenticate() How do I run authenticate() once 'home' state has loaded? 一旦'home'状态加载,我如何运行authenticate()?

Additionally, can I tell angular to only load authenticate.js for this state? 另外,我可以告诉angular只为这个状态加载authenticate.js吗? Or should I have already loaded it in the template. 或者我应该已经将其加载到模板中。 I know that if I include the script in partial-home.html (eg <script src="authenticate.js"></script> ) chrome throws me an error about synchronous xmlhttprest being deprecated. 我知道如果我将该脚本包含在partial-home.html中(例如<script src="authenticate.js"></script> ),chrome会抛出一个关于同步xmlhttprest被弃用的错误。 So somhow in the config, can I declare authenticat.js as a dependency of the state or something like that? 所以somhow在配置中,我可以声明authenticat.js作为状态的依赖或类似的东西吗?

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. 然后定义控制器在我的ui-router状态中进行身份验证。 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. 我的身份验证功能正在做更改DOM中的事情,但我不应该使用控制器。

Thanks for any pointers 谢谢你的任何指示

Let's break down into parts. 让我们分解成几部分。

If you just want to load authenticate.js in this particular home state, use ocLazyLoad . 如果您只想在此特定的home状态下加载authenticate.js ,请使用ocLazyLoad It's one of the best way to load a resource lazily. 这是懒惰加载资源的最佳方式之一。 And it works really well if ui-router too! 如果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. 如果要在加载状态后运行authenticate() ,则可以通过多种方式执行此操作。 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. 当然,一种方法是监听$stateChangeSuccess事件,但我会避免使用它,因为你知道,全局变量和全局变量都很糟糕。 I do not want to pollute my $rootScope just because I have a really specific use case. 我不想因为我有一个非常具体的用例而污染我的$rootScope

You can use resolve in ui-router too. 您也可以在ui-router中使用resolve Resolve is executed after the state is loaded and before the controller is instantiated. 在加载状态之后实例化控制器之前执行Resolve I would recommend to use this method as you can chain your promises together with ocLazyLoad , if you are using it (which you should). 我建议使用这种方法,因为你可以将你的承诺与ocLazyLoad一起ocLazyLoad ,如果你正在使用它(你应该)。

Manipulating DOMs after a state is loaded? 在加载状态后操纵DOM? Sure, that's what templateUrl for! 当然,这就是templateUrl用途! Design your template such that it accomadates to your authenticate() functions. 设计您的模板,使其符合您的authenticate()函数。 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. 如果将它与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. 你想先懒洋洋地加载authenticate.js ,然后用函数内部 authenticate.js做一些事情。 Since resolve in ui.router executes promise chains in parallel, we have to chain them up, ie, load your jsfiles first, and then return your status of authentication. 既然resolveui.router并行执行承诺链,我们必须把它们连起来,即先加载jsfiles,然后回到您的身份验证的状态。

We need to declare a deferred promise using $q service. 我们需要使用$q服务声明延迟的承诺。 We then return this promise in the resolve, so that you controller is listening to one promise instead of two. 然后我们在决心中返回此承诺,以便您的控制器正在听一个承诺而不是两个承诺。 Here is how: 方法如下:

 $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.

}]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM