javascript - Är $timeout fortfarande bästa praxis för att vänta på Angular-direktivets mall?


Vårt teams designmönster för att vänta på att en direktivs mall ska renderas är att omsluta vår DOM-manipulationskod i en $timeout (inuti direktivets länkfunktion), vilket jag vet vid en tidpunkt var det normala designmönstret. Är det fortfarande sant, eller finns det bättre/säkrare designmönster för att göra detta?

Exempel på mönster finns i ECMAScript6:

link: ($scope, $element) => {
  $timeout(() => {
     var domElementFromTemplate = $element.find('myDOMElement');
  } 
}

Svar #1

Medan du försöker välja ett element som finns i DOM:

Det har aldrig varit en bästa praxis enligt min åsikt eftersom det inte finns något behov av att skapa ett asynkront beteende för en synkron DOM-urvals-funktion. Enligt angular.element-dokumentationen bör det se ut så här:

link: ($scope, $element) => {
    var domElementFromTemplate = $element.find('myDOMElement');
}

Medan du försöker välja ett element som ska renderas i din direktiv:

Timeout-funktionen bör undvika DOM-renderad asynkron beteende, men enligt min åsikt finns det många bättre tillvägagångssätt för att hantera detta problem:


Lösning 1)

Ett annat tillvägagångssätt är att få dokumentets färdiga tillstånd för att säkerställa att ditt element är tillgängligt i DOM, som:

link: ($scope, $element) => {
    angular.element(document).ready(() => {
        var domElementFromTemplate = $element.find('myDOMElement');
    });
}

Lösning 2)

Ett annat tillvägagångssätt är att skapa en annan direktiv för de element som renderades inuti en direktiv, t.ex. (myDOMElement) för att helt undvika DOM-injektion.

link: ($scope, $element) => {},
template: "<div some-other-child-directive></div>"

Lösning 3)

Det borde vara ett mycket bättre och mer ordnat tillvägagångssätt att skapa en callback-funktion för att säkerställa att elementet är tillgängligt i DOM. Detta kan göras med ng-init="someCallback()" för att starta dina elementfunktioner.


Lösning 4)

Ja, att använda $timeout fungerar fortfarande fint medan en ny $timeout kommer att läggas till i exekveringskön och kommer att köras efter att DOM har renderats. Ett timeout-fördröjningsvärde behövs inte.

link: ($scope, $element) => {
    $timeout(() => {
        var domElementFromTemplate = $element.find('myDOMElement');
    }
}

Relaterade artiklar