ChatGPT解决这个技术问题 Extra ChatGPT

Difference between the 'controller', 'link' and 'compile' functions when defining a directive

Some places seem to use the controller function for directive logic and others use link. The tabs example on the angular homepage uses controller for one and link for another directive. What is the difference between the two?

Perhaps a more comprehensive overview of directive functions: Angular directives - when to use compile, controller, pre-link and post-link.

C
Community

I'm going to expand your question a bit and also include the compile function.

compile function - use for template DOM manipulation (i.e., manipulation of tElement = template element), hence manipulations that apply to all DOM clones of the template associated with the directive. (If you also need a link function (or pre and post link functions), and you defined a compile function, the compile function must return the link function(s) because the 'link' attribute is ignored if the 'compile' attribute is defined.)

link function - normally use for registering listener callbacks (i.e., $watch expressions on the scope) as well as updating the DOM (i.e., manipulation of iElement = individual instance element). It is executed after the template has been cloned. E.g., inside an

  • , the link function is executed after the
  • template (tElement) has been cloned (into an iElement) for that particular
  • element. A $watch allows a directive to be notified of scope property changes (a scope is associated with each instance), which allows the directive to render an updated instance value to the DOM.

    controller function - must be used when another directive needs to interact with this directive. E.g., on the AngularJS home page, the pane directive needs to add itself to the scope maintained by the tabs directive, hence the tabs directive needs to define a controller method (think API) that the pane directive can access/call. For a more in-depth explanation of the tabs and pane directives, and why the tabs directive creates a function on its controller using this (rather than on $scope), please see 'this' vs $scope in AngularJS controllers.

    In general, you can put methods, $watches, etc. into either the directive's controller or link function. The controller will run first, which sometimes matters (see this fiddle which logs when the ctrl and link functions run with two nested directives). As Josh mentioned in a comment, you may want to put scope-manipulation functions inside a controller just for consistency with the rest of the framework.


    This explanation should be in the main AngularJS docs or at least a reference to it
    This is an informative answer but I think that it's difficult to read. Perhaps more punctuation and smaller sentences can help. Overall I'm grateful for the answer.
    The $compiler ignores the 'link' attribute in the presence of a 'compile' attribute. But what about in the presence of a 'controller' attribute? Does 'controller' cause the $compiler to ignore either or both 'link' and 'compile' attributes? Is it possible and/or advisable to use a 'compile' together with a 'controller'?
    @CarlG, the presence of a controller attribute has no effect on the $compiler with regards to the link and compile. You can use compile and controller.
    "DOM listeners" are NOT "(i.e., $watch expressions on the scope)". One listens to the DOM for events like mouseover, the other to the scope for property changes. Big difference.
  • P
    Pixic

    As complement to Mark's answer, the compile function does not have access to scope, but the link function does.

    I really recommend this video; Writing Directives by Misko Hevery (the father of AngularJS), where he describes differences and some techniques. (Difference between compile function and link function at 14:41 mark in the video).


    +1 for the link to the video. It is very informative.
    R
    Rahul

    running code before Compilation : use controller running code after Compilation : use Link

    Angular convention : write business logic in controller and DOM manipulation in link.

    Apart from this you can call one controller function from link function of another directive.For example you have 3 custom directives

    <animal>
    <panther>
    <leopard></leopard>
    </panther> 
    </animal>
    

    and you want to access animal from inside of "leopard" directive.

    http://egghead.io/lessons/angularjs-directive-communication will be helpful to know about inter-directive communication


    "running code before Compilation: use controller". This is incorrect; compile will always be executed before controller.
    You would not (at least not in a straightforward way) be able to access animal from your leopard directive. Child directives can access controller methods in a parent directive, but sibling directives (like in the example above) cannot call one another's controllers.
    Are leopards really a type of panther? Also, on a side note... Can you have a link -- AND -- a controller in a directive?
    yes leopard/jaguars are panthers. and yes you have link and controller within directive.
    From the Angular developer guide: "Best Practice: use controller when you want to expose an API to other directives. Otherwise use link."
    S
    Sunil Garg

    compile function -

    is called before the controller and link function. In compile function, you have the original template DOM so you can make changes on original DOM before AngularJS creates an instance of it and before a scope is created ng-repeat is perfect example - original syntax is template element, the repeated elements in HTML are instances There can be multiple element instances and only one template element Scope is not available yet Compile function can return function and object returning a (post-link) function - is equivalent to registering the linking function via the link property of the config object when the compile function is empty. returning an object with function(s) registered via pre and post properties - allows you to control when a linking function should be called during the linking phase. See info about pre-linking and post-linking functions below.

    syntax

    function compile(tElement, tAttrs, transclude) { ... }
    

    controller

    called after the compile function scope is available here can be accessed by other directives (see require attribute)

    pre - link

    The link function is responsible for registering DOM listeners as well as updating the DOM. It is executed after the template has been cloned. This is where most of the directive logic will be put. You can update the dom in the controller using angular.element but this is not recommended as the element is provided in the link function Pre-link function is used to implement logic that runs when angular js has already compiled the child elements but before any of the child element's post link have been called

    post-link

    directive that only has link function, angular treats the function as a post link post will be executed after compile, controller and pre-link funciton, so that's why this is considered the safest and default place to add your directive logic