2

我正在尝试使用属性指令将元素的模板引用从父组件传递到使用依赖注入的嵌套组件,但父组件中获取目标元素的指令实例与被注入到嵌套组件中——正在创建指令的第二个实例,它不访问目标元素,这就是被注入的那个。

这是基本结构:

<div>
  <div #myTarget [appendTarget]="myTarget"></div>
  <child>
    <grandchild></grandchild>
  </child>
</div>

我试图传递对#myTargetdown的引用以<grandchild>使用 DirectiveappendTarget和 DI 而不是@Inputs (工作正常),因此<child>不需要了解它并充当传递。

我已经包含AppendTargetDirectiveproviders父组件的数组中:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [
    AppendTargetDirective
  ]
})
export class AppComponent {
  constructor() { }
}

并将其注入<grandchild>组件中:

@Component({
  selector: 'grandchild',
  template: `
<div>
  Hi! Grandchild here...
</div>
  `
})
export class GrandchildComponent  {
  constructor(
    private appendTargetDirective: AppendTargetDirective
  ) {}
}

但是,有两个实例AppendTargetDirective被创建,一个获取对的引用#myTarget,一个不获取引用,并且GrandchildComponent正在获取后者。

这是一个 StackBlitz演示这个问题。如果您打开控制台,您会看到 Directive 构造函数被调用了两次(我在其构造函数中为每个实例生成一个唯一 ID),并且获取目标元素的实例不是被注入的实例. 我认为将它包含在providers父组件的数组中会创建一个它的单个实例,该实例将在父组件及其后代之间共享,但显然我的想法不正确。

任何帮助将不胜感激。

4

1 回答 1

1

永远不应该将 Angular 指令添加到providers数组中。Angular 会将它们视为服务,它们是指令类的独立实例,根本不依赖于模板结构。

以下是 Angular 如何尝试解决您的情况下的指令依赖关系。

它从当前元素开始并向上走

  3 ^  <div>
        <div #myTarget [appendTarget]="myTarget"></div>
  2 ^     <child>   
  1 ^       <grandchild></grandchild>
          </child>
       </div>

如果您将指令放在放置您孩子的 HTML 树的同一分支上,则指令的 DI 将起作用:

<div>
  <div #myTarget></div>
  <child [appendTarget]="myTarget">   <--------------------------- move it here
    <grandchild></grandchild>
  </child>
</div>

分叉的 Stackblitz

于 2020-07-25T04:06:05.113 回答