AngularJS:我应该将指令的链接功能转换为控制器吗? [英] AngularJS: Should I convert directive's linking function to a controller?

查看:25
本文介绍了AngularJS:我应该将指令的链接功能转换为控制器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说在使用隔离范围的指令中使用 controllerAs 语法和 bindToController: true 是一个很好的做法.参考资料:一个两个

假设,我有一个这样的指令:

angular.module('MyModule').directive('MyDirective', function(User) {返回 {范围: {名称:'='},templateUrl: 'my-template.html',链接:功能(范围){scope.User = 用户;scope.doSomething = 函数(){//做一些很酷的事情};}};});

<div>用户 ID:{{ User.id }}姓名:{{姓名}}<button ng-click="doSomething()">做它</button>

如您所见,该指令中没有控制器.但是,为了能够利用 controllerAsbindToController: true 我必须有一个控制器.

将链接函数转换为控制器的最佳做法是什么?

angular.module('MyModule').directive('MyDirective', function(User) {返回 {范围: {名称:'='},templateUrl: 'my-template.html',bindToController: 真,controllerAs: 'myCtrl',控制器:函数(){this.User = 用户;this.doSomething = 函数(){//做一些很酷的事情};}};});

<div>用户 ID:{{ myCtrl.User.id }}名称:{{ myCtrl.name }}<button ng-click="myCtrl.doSomething()">做它</button>

我的理解是指令的控制器应该用作一种机制来公开指令的 API 以进行指令到指令的通信.

有没有人可以说明目前考虑到 Angular 2.0 的最佳实践是什么?

解决方案

我认为最好的做法是在指令的控制器内部移动初始化代码和/或暴露 API 函数,因为它有两个目的:

<代码>1.$scope 的初始化2. 暴露一个 API 用于指令之间的通信

范围初始化

假设您的指令定义了一个子作用域(或继承作用域).如果在链接函数内部初始化作用域,则子作用域将无法通过作用域继承访问此处定义的任何作用域变量.这是因为父链接函数总是在子链接函数之后执行.因此,作用域初始化的正确位置是在控制器函数内部.

公开控制器 API

子指令可以通过指令定义对象上的require"属性访问父指令的控制器.这允许指令进行通信.为了使其工作,必须完全定义父控制器,以便可以从子指令的链接函数访问它.实现这一点的最佳位置是在控制器函数本身的定义中.父控制器函数总是在子控制器函数之前调用.

最后的想法

了解链接功能和控制器功能服务于两个截然不同的目的很重要.控制器函数是为初始化和指令通信而设计的,而链接器函数是为运行时行为而设计的.根据您的代码的意图,您应该能够决定它是属于控制器还是属于链接器.

是否应该将任何用于初始化范围的代码从链接函数移动到控制器函数?

是的,这是控制器函数存在的主要原因之一:初始化范围,并允许其范围参与原型范围继承.

是否应该将 $watch 处理程序从链接函数移动到控制器函数?

没有.link 函数的目的是连接行为并可能操纵 DOM.在链接函数中,所有指令都已经编译完成,所有子链接函数都已经执行.这使它成为连接行为的理想场所,因为它尽可能接近 DOM(在 Render 阶段之后才真正准备好 DOM).

I heard it's a good practice to use the controllerAs syntax along with bindToController: true in directives that use an isolate scope. References: one, two

Suppose, I have a directive like this:

angular.module('MyModule').directive('MyDirective', function(User) {
  return {
    scope: {
      name: '='
    },
    templateUrl: 'my-template.html',
    link: function(scope) {
      scope.User = User;
      scope.doSomething = function() {
        // Do something cool
      };
    }
  };
});

<!-- my-template.html -->
<div>
  User Id: {{ User.id }}
  Name: {{ name }}
  <button ng-click="doSomething()">Do it</button>
</div>

As you can see, there is no controller in this directive. But, to be able to leverage controllerAs and bindToController: true I have to have a controller.

Is the best practice to convert the linking function to a controller?

angular.module('MyModule').directive('MyDirective', function(User) {
  return {
    scope: {
      name: '='
    },
    templateUrl: 'my-template.html',
    bindToController: true,
    controllerAs: 'myCtrl',
    controller: function() {
      this.User = User;
      this.doSomething = function() {
        // Do something cool
      };
    }
  };
});

<!-- my-template.html -->
<div>
  User Id: {{ myCtrl.User.id }}
  Name: {{ myCtrl.name }}
  <button ng-click="myCtrl.doSomething()">Do it</button>
</div>

My understanding is that directive's controller should be used as a mechanism to expose directive's API for a directive-to-directive communication.

Could anyone shed light on what's the best practice these days, having Angular 2.0 in mind?

解决方案

I consider it best practice to move initialization code and/or exposing API functions inside of a directive's controller, because it serves two purposes:

1. Intialization of $scope 
2. Exposing an API for communication between directives

Initialization of Scope

Suppose your directive defines a child scope (or inherits scope). If you initialize scope inside of your link function, then child scopes will not be able to access any scope variables defined here through scope inheritance. This is because the parent link function is always executed after the child link function. For this reason, the proper place for scope initialization is inside of the controller function.

Exposing a Controller API

Child directives can access the parent directive's controller through the 'require' property on the directive definition object. This allows directives to communicate. In order for this to work, the parent controller must be fully defined, so that it can be accessed from the child directive's link function. The best place to implement this is in the definition of the controller function itself. Parent controller functions are always called before child controller functions.

Final Thoughts

It is important to understand that the link function and the controller function serves two very different purposes. The controller function was designed for initialization and directive communication, and the linker function was designed for run-time behavior. Based on the intent of your code, you should be able to decide whether it belongs in the controller, or it belongs in the linker.

Should you move any code that initializes scope from the link function to the controller function?

Yes, that is one of the primary reasons that the controller function exists: to initialize scope, and allow its scope to participate in prototypical scope inheritance.

Should you move $watch handlers from the link function to the controller function?

No. The purpose of the link function is to hookup behavior and potentially manipulate the DOM. In the link function, all directives have been compiled, and all child link functions have already executed. This makes it an ideal place to hookup behavior because it is as close DOM ready as it can be (it is not truly DOM ready until after the Render phase).

这篇关于AngularJS:我应该将指令的链接功能转换为控制器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆