欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解angularjs利用ui-route异步加载组件

程序员文章站 2022-04-09 12:52:50
ui-route相比于angularjs的原生视图路由更好地支持了路由嵌套,状态转移等等。随着视图不断增加,打包的js体积也会越来越大,比如我在应用里面用到了wangedi...

ui-route相比于angularjs的原生视图路由更好地支持了路由嵌套,状态转移等等。随着视图不断增加,打包的js体积也会越来越大,比如我在应用里面用到了wangeditor里面单独依赖的jquery就300多k。异步加载各个组件就很有必要。在这里我就以ui-route为框架来进行异步加载说明。

首先看一下路由加载文件

angular.module('webtrn-sns').config(['$stateprovider', function ($stateprovider) {
  $stateprovider.state({
      name: 'home.message',
      url: '/message',
      abstract: true,
      templateprovider: ['resources', function (resources) {
        return resources.template
      }],
      controllerprovider: ['resources', (resources)=> {
        return resources.controller
      }],
      onenter: ['resources', (resources)=>resources.css.use()],
      onexit: ['resources', (resources)=>resources.css.unuse()],
      resolve: {
        resources: ()=> {
          return new promise(
            resolve => {
              require([], () => {
                resolve({
                  css: require('./css/message_box.css'),
                  template: require('./html/message_box.html'),
                  controller: require('./js/message_box.js')
                })
              })
            }
          );
        }
      }
    }
  ).state({
      name: 'home.message.add_message',
      url: '/add_message?isreply&touid&title',
      params: {isreply: null, touid: null, title: null},
      templateprovider: ['resources', function (resources) {
        return resources.template
      }],
      controllerprovider: ['resources', (resources)=> {
        return resources.controller
      }],
      onenter: ['resources', (resources)=>resources.css.use()],
      onexit: ['resources', (resources)=>resources.css.unuse()],
      resolve: {
        resources: ()=> {
          return new promise(
            resolve => {
              require(['./js/message.js'], () => {
                resolve({
                  css: require('./css/add_message.css'),
                  template: require('./html/add_message.html'),
                  controller: require('./js/add_message.js')
                })
              })
            }
          );
        }
      }
    }
  )
}])

这个是路由状态的一个声明文件,name,url,param字段的方式不变,关键是看resolve这个部分。根据ui-route的resolve文档,resolve是为了给state或者controller进行自定义注入对象的。

下面是举出文档中关于resolve的例子:

$stateprovider.state('mystate', {
   resolve:{
     // example using function with simple return value.
     // since it's not a promise, it resolves immediately.
     simpleobj: function(){
      return {value: 'simple!'};
     },
     // example using function with returned promise.
     // this is the typical use case of resolve.
     // you need to inject any services that you are
     // using, e.g. $http in this example
     promiseobj: function($http){
      // $http returns a promise for the url data
      return $http({method: 'get', url: '/someurl'});
     },
     // another promise example. if you need to do some 
     // processing of the result, use .then, and your 
     // promise is chained in for free. this is another
     // typical use case of resolve.
     promiseobj2: function($http){
      return $http({method: 'get', url: '/someurl'})
        .then (function (data) {
          return dosomestufffirst(data);
        });
     },    
     // example using a service by name as string.
     // this would look for a 'translations' service
     // within the module and return it.
     // note: the service could return a promise and
     // it would work just like the example above
     translations: "translations",
     // example showing injection of service into
     // resolve function. service then returns a
     // promise. tip: inject $stateparams to get
     // access to url parameters.
     translations2: function(translations, $stateparams){
       // assume that getlang is a service method
       // that uses $http to fetch some translations.
       // also assume our url was "/:lang/home".
       return translations.getlang($stateparams.lang);
     },
     // example showing returning of custom made promise
     greeting: function($q, $timeout){
       var deferred = $q.defer();
       $timeout(function() {
         deferred.resolve('hello!');
       }, 1000);
       return deferred.promise;
     }
   },
   // the controller waits for every one of the above items to be
   // completely resolved before instantiation. for example, the
   // controller will not instantiate until promiseobj's promise has 
   // been resolved. then those objects are injected into the controller
   // and available for use. 
   controller: function($scope, simpleobj, promiseobj, promiseobj2, translations, translations2, greeting){
     $scope.simple = simpleobj.value;
     // you can be sure that promiseobj is ready to use!
     $scope.items = promiseobj.data.items;
     $scope.items = promiseobj2.items;
     $scope.title = translations.getlang("english").title;
     $scope.title = translations2.title;
     $scope.greeting = greeting;
   }
  })

我们可以看到resolve的对象是支持promise的。

再回到我们之前的代码templateprovider和controllerprovider我们注入了resources的模板对象和controller对象,onenter和onexit注入了css模块。

如果controller中依赖了服务怎么办的?

resolve: {
  resources: ()=> {
    return new promise(
      resolve => {
        require(['./js/message.js'], () => {
          resolve({
            css: require('./css/add_message.css'),
            template: require('./html/add_message.html'),
            controller: require('./js/add_message.js')
          })
        })
      }
    );
  }
}

可以在require里面将服务注入,如代码中的message.js。而为了将服务进行异步加载我们不能用普通的.factory或者.service。而需要调用$provide.factory或者$provide.service

如果采用webpack进行编译打包的话就需要webpack.optimize.commonschunkplugin的支持,这样可以对js进行拆分打包,达到异步加载js的目的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。