使用 ui 路由器的范围和控制器实例化 [英] scope and controller instantiation with ui router

查看:27
本文介绍了使用 ui 路由器的范围和控制器实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对控制器何时被实例化感到困惑.此外,在嵌套状态时如何实例化控制器.我可能会困惑范围如何附加到视图和控制器上,也就是说,如果每个视图都有自己的控制器和范围,或者它们是否共享相同的范围.

I am confused about when controllers get instantiated. Also, how do controllers gets instantiated when nesting states. I might be confused how scope gets attached to view and controller, that is, if every view gets its own controller and scope or do they share the same scope.

谁能解释一下控制器何时被实例化?在嵌套路由下,所有视图是否共享一个控制器和作用域?当我切换状态并返回到另一个控制器被实例化的状态时会发生什么?

Can someone please explain when controllers get instantiated? Under nested routes do all the views share one controller and scope? What happens when I switch states and go back to a state does another controller get instantiated?

以下是我的路线(配置文件):

Below are my routes(config file ):

.config (googleAnalyticsCordovaProvider, $stateProvider, $urlRouterProvider, IdleProvider, KeepaliveProvider) ->

   $stateProvider

  .state('app', {
    url: '/app',
    abstract: true,
    templateUrl: 'templates/menu.html',
    controller: 'AppController'
  })

  .state('app.pincode', {
    url: '/pincode',
    views: {
      menuContent: {
        templateUrl: 'templates/pincode-yield.html',
        controller: 'PincodeController'
      }
    }
  })

  .state('app.pincode.create', {
    url: '/create',
    views: {
      pincode: {
        templateUrl: 'templates/pincode-create.html',
        controller: 'PincodeController'
      }
    }
  })

  .state('app.pincode.pincodeLogin', {
    url: '/login',
    views: {
     pincode: {
        templateUrl: 'templates/pincode-login.html',
        controller: 'PincodeController'
      }
    }
  })

  .state('app.pincode.settings', {
    url: '/settings',
    views: {
      pincode: {
        templateUrl: 'templates/settings.html',
        controller: 'PincodeController'
      }
    }
  })

推荐答案

要获得更详细的答案,我们可以/应该观察源代码并查看文档.让我尝试解释所有三个问题(并从代码和文档中引用).

To get even more detailed answers, we can/should observe the source code and check the documentation. Let me try to explain all three questions (and also cite from code and doc).

1.控制器什么时候实例化?

这里我们可以观察到ui-view指令的代码:

Here we can observe the code of the ui-view directive:

[$ViewDirective.$inject = \['$state', '$injector', '$uiViewScroll', '$interpolate'\];][1]

控制器与视图相关.那些 views,在 .state() 内部定义为 views 对象:

Controllers are related to views. Those views, which are defined inside of a .state() as the views object:

.state('...', {
  // The view definition
  views : {
    '' : {
      template: ...
      controller: ...
      resolve: ..
    }
  },
  resolve: ...
}

因此,每当 view(ui-view)填充状态视图中定义的设置时,它几乎充当标准,但增强指令.

So, whenever is view (the ui-view) filled with settings defined inside of a state view, it acts almost as a standard, but enhanced directive.

1) 找到模板,
2) 解析被解析
...
x) 控制器实例化...

1) Template is found,
2) Resolves are resolved
...
x) Controller is instantiated...

视图目标(ui-view 指令)可以使用名称,并且可以由层次结构中的不同状态填充.

View targets (ui-view directives) could use names, and could be filled by different states in the hierarchy.

这可能意味着,一个视图中可能有一个内容(例如 title),由 parent 定义并被替换孩子

It could mean, that there could be a content inside of one view (e.g. title), defined by parent as well as replaced by child

// parent
.state('parent', {
  views : {
    '' : {...} // the main parent view, with ui-view="title"
    'title@parent' : { ...} // here we go and fill parent's ui-view="title"
  },
  ...
}

// child
.state('parent.child', {
  views : {
    'title' : { ...} // here we change the parent's target ui-view="title"
  },
  ...
}

上面的状态定义将(每当我们在这两个状态之间转换时):

  • $state.go('parent') - 'title@parent' 中定义的视图(模板、控制器...):{ ...} 将被注入到目标 ui-view="title" 并如上所述实例化

  • The $state.go('parent') - the view (template, controller...) defined in 'title@parent' : { ...} will be injected into target ui-view="title" and instantiated as described above

$state.go('parent.child') - 几乎相同,只是视图将取自子状态/视图定义 'title' : {...}.这将替换 ui-view="title" 的内容,并将按上述方式实例化

The $state.go('parent.child') - almost the same, just the view will be taken from child state/view defintion 'title' : { ...}. That will replace the content of the ui-view="title" and will be instantiated as described above

每次我们从父母到孩子从孩子到父母时都会发生这种情况.

This will be happening every time we do go from parent to child and from child to parent.

2.在嵌套路由下,所有视图是否共享一个控制器和作用域?

一个简单的答案是NO没有共同分享.

A simple answer is NO, there is no common sharing.

事实上,每个控制器都有自己的作用域,它是从父视图作用域创建的.首先是文档:

In fact, each controller has its own scope, the one which is created from parent view scope. Firstly the documentation:

...

请记住,如果您的状态的视图是嵌套的,那么范围属性只会沿状态链向下继承.范围属性的继承与状态的嵌套无关,而与视图(模板)的嵌套有关.

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

您完全有可能拥有嵌套状态,其模板会在您站点内的各种非嵌套位置填充 ui-view.在这种情况下,您不能期望在子状态的视图中访问父状态视图的范围变量.

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.

所以,无论何时,我们的 controller (以及带有模板、控制器的 view...) 注入父对象的目标 ui-view="..." 它获得继承范围:

So, whenever is our controller (well the view with template, controller...) injected into parent's target ui-view="..." it gets inherited scope:

newScope = scope.$new();

简而言之,这意味着 JS 对象 (例如 scope.Model = {}) 可以在子级和父级之间共享.

That in a nutshell means that JS objects (e.g. scope.Model = {}) can be shared among child and parent.

$scope.Model.id = 1; // will refer to the same id in both parent & child

然而,基本的 Javascript 类型不是通过引用传递的,因此它们的值不会在范围之间自动同步:

However, basic Javascript types are not passed by reference, and so their values are not automatically synchronised between scopes:

// set in parent
$scope.id = 1;
// in child after inherted still === 1
$scope.id = 2; // now 2 for a child, different value in parent - still === 1

值得在这里阅读更多关于原型继承的内容:
AngularJS 中范围原型/原型继承的细微差别是什么?

It's worth reading more about prototypical inheritance here:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

3.当我切换状态并返回一个状态时会发生什么 - 另一个控制器是否被实例化?

这取决于.

如果父子视图(记住上面的ui-view="title")被子视图替换,然后重新创建(从孩子过渡到父母) - 这样的控制器将被重新初始化(上面讨论过).

If the parent sub view (remember ui-view="title" above) is replaced by child view, and then it is re-created (transitioning from child to parent) - such controller wil be re-initialized (discussed above).

但是当我们谈到主父视图(通常未命名)时,它代表父视图(例如未命名的父视图)使用控制器'ParentMainCtrl'查看下方)

But when we speak about the main parent view (usually unnamed), which represents the parent (For example the unnamed view below with controller 'ParentMainCtrl')

.state('parent', {
  views : {
    '' : {  //  // the main parent view
      controller: 'ParentMainCtrl',
    }
    'title@parent'
    'tooltip@parent'
  },

然后我们可以确定这样的控制器不会被重新实例化.它存在于其所有孩子的生命周期中,加上父母的一个(未选择孩子状态).

Then we can be sure that such controller is NOT re-instantiated. It lives during the lifetime of all its children, plus a parent's one (no child state selected).

要重新加载这个视图/控制器,我们必须使用一个选项 reload

To re-load this view/controller, we have to use an option reload

...选项 选项对象.选项是:

... options Options object. The options are:

  • ...
  • reload - {boolean=false},如果为 true,即使状态或参数没有改变,也会强制转换,也就是重新加载同一个状态.它与 reloadOnSearch 不同,因为当您想在所有内容(包括搜索参数)都相同时强制重新加载时,您会使用它.
  • 希望能有所帮助.如需更多信息,请查看以下资源:

    Hope that helps a bit. For further information, check out these resources:

    • Nested States & Nested Views
    • Multiple Named Views
    • API Reference
    • State.js of the sample application - I would say the best documented piece of code ever

    这篇关于使用 ui 路由器的范围和控制器实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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